一直感觉 javascript
中的 this
是一个大坑,虽然一直都有注意,一直都有研究,但是总是会忘记。在这里,总结一下一些简单的规律
下面的所有的都是不考虑箭头函数的情况下,因为箭头函数和普通的差别很大
除非是 bind
绑定过的 ,其他情况下,直接调用的方法的 this
都是 window
。所谓的直接调用,就是直接以 method()
的形式调用,没有 call
, apply
, new
看几种情况:
function foo(){ return this; } foo(); // window
var obj = { foo: function(){ return this; } } var foo = obj.foo; foo(); // window
function Foo(){ this.foo = function(){ console.log(this); } var foo = this.foo; foo(); // window } new Foo();
除非是 bind
绑定过的 ,一般情况下,谁调用这个方法,那么内部的 this
就指向这个对象。也就是说 obj.method()
,那么就指向 obj
。 obj.foo.method()
,那么就指向 obj.foo
看几个例子:
var obj = { foo: function(){ return this; } } obj.foo(); // obj调用,所以结果是obj
function foo(){ return this }; var obj = {}; obj.foo = foo; obj.foo(); // obj调用,所以结果是obj
var obj = { bar: function(){ return this; }, foo: function(){ return this.bar(); } } obj.foo(); // 在foo中, this是obj, 而this调用的bar, 所以返回的是obj
var obj = { bar: { foo: function(){ return this } } } obj.bar.foo(); // obj.bar调用的foo,所以返回的结果是bar
function foo(){ this.bar = function(){ return this } return this.bar(); } foo(); // 由于foo中的this是window, 所以this.bar()返回的是window
function Foo(){ this.foo = function(){ console.log(this); } this.foo(); } var object = new Foo(); // 由于this.foo中的this是object,所以this是object
所有情况下,(箭头函数不能使用 new
关键字),使用了 new
以后,会把内部的 this
指向新生成的对象。
除去bind的情况下, prototype
中的 this
也指向新生成的对象
function Foo(){ console.log(this); // this指向新生成的对象,object } var object = new Foo();
function Foo(){ this.foo = function(){ return this === object; } } var object = new Foo(); object.foo(); // 输出true
function Foo(){} Foo.prototype.foo = function(){ return this === object; } var object = new Foo(); object.foo(); // 输出true
除非是bind的情况, call
, apply
是谁,那么内部的 this
就是谁。
注意:如果是基本类型,那么 javascript
会把基本类型转换成 Object
的形式
也是看例子:
function foo(){ return this; } foo.call("a"); // String typeof foo.call("a"); // object
var obj = { foo : function(){ return this; } } obj.foo.call(1); // Number typeof obj.foo.call(1); // object
function Foo(){ this.foo = function(){ return this; } } var object = new Foo(); object.foo.call(1); // Number
除了 new
这一种特殊情况 , bind
的对象是谁,那么 this
也就是谁。即使 call
, apply
也没有权利改变。
注意:如果是基本类型,那么 javascript
会把基本类型转换成 Object
的形式
function foo() { return this; } foo = foo.bind(1); foo(); // Number typeof foo(); // object
function foo() { return this; } foo = foo.bind(1); foo.call("a"); // Number 1
function Foo() { return this; } Foo.prototype.foo = (function(){ return this; }).bind(1); var object = new Foo(); object.foo(); // Number
特殊情况
new
这个关键词可以改变方法内部的 this
,使他指向新生成的对象
function Foo(){ this.foo = function(){ console.log(this === obj) } } Foo = Foo.bind(1); var obj = new Foo(); obj.foo(); // 输入true
箭头函数的 this
是根据定义环境的 this
来定的,也就是说定义的函数周围的 this
是什么,它的 this
就是什么。
而且不会被 bind
, call
, apply
所改变
var foo = ()=>{ return this }; foo() // window
var obj = { foo: ()=>this } obj.foo(); // 由于定义的时候,周围的环境是window,所以返回window
var obj = { foo(){ var bar= ()=>{ return this }; return bar(); } } obj.foo(); // 由于定义bar的时候,周围环境是obj,所以返回obj var foo = obj.foo; foo(); // 同理,这里是window
var foo = ()=>{ return this }; foo = foo.bind(1); foo(); // window foo.call(1); // window foo.apply(1); // window
function Foo(){ // 箭头函数 var a = ()=>{ console.log(this === object); // true } // 对比普通函数 var b = function(){ console.log(this === window); // true } this.foo = function(){ a(); b(); } } var object = new Foo(); object.foo();
function Foo(){} // window Foo.prototype.foo = ()=>{ return this } // window var object = new Foo(); object.foo(); // 由于定义foo的时候,周围环境是window,所以这里是window
由于只是我根据经验和资料自己总结的,所以不知道是否有疏忽或者遗漏,如果有问题的地方,欢迎提出。谢谢