一、this是什么?
this是指包含它的函數(shù)作為方法被調(diào)用時(shí)所屬的對(duì)象。
二、由new調(diào)用(new綁定),綁定到新創(chuàng)建的對(duì)象
new表達(dá)式:
function foo(a) {
this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2
三、由call 、apply、bind 調(diào)用(顯示綁定),綁定到指定的對(duì)象
顯示綁定:可以直接指定this的綁定對(duì)象,例如call()、apply()。
1.call ( 傳的this,參數(shù)用逗號(hào)隔開 )
2.aplay(傳的this,【參數(shù)用數(shù)組形式】)
3.bind 返回的是一個(gè)新的函數(shù),必須調(diào)用它才會(huì)被執(zhí)行,它的參數(shù)和 call 一樣。
注意:
如果第一個(gè)參數(shù)傳的是null,和undefined ,this會(huì)指向window;
如果是number、string、boolean會(huì)轉(zhuǎn)向包裝類型。
四、由上下文調(diào)用(隱式綁定),綁定到那個(gè)上下文對(duì)象
隱式綁定:會(huì)把函數(shù)調(diào)用的this綁定到這個(gè)上下文對(duì)象。
注意:隱式綁定的函數(shù)如果丟失了綁定的對(duì)象,就會(huì)應(yīng)用默認(rèn)綁定,從而吧this綁定到全局對(duì)象或者undefined上,取決于是否是嚴(yán)格模式。
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
下面的this的指向是window,并不是foo。
function foo(num) {
console.log( "foo: " + num );
// keep track of how many times `foo` is called
this.count++;
}
foo.count = 0;
var i;
for (i=0; i<10; i++) {
if (i > 5) {
foo( i );
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
// how many times was `foo` called?
console.log( foo.count ); // 0 -- WTF?

五、用 call-site 和 call-stack 來(lái)查找上下文調(diào)用時(shí)this的指向
call-site:調(diào)用位置,函數(shù)在代碼中被調(diào)用的位置(不是聲明的位置)。
call-stack:調(diào)用棧,就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù)??梢詮恼{(diào)用棧中分析出真正的調(diào)用位置,因?yàn)樗鼪Q定了this的綁定。
function foo() {
console.log( this.a );
}
var obj2 = {
a: 42,
foo: foo
};
var obj1 = {
a: 2,
obj2: obj2
};
obj1.obj2.foo(); // 42
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // function reference/alias!
var a = "oops, global"; // `a` also property on global object
bar(); // 調(diào)用位置 "oops, global"
這里bar是obj.foo的一個(gè)引用,它引用的是foo函數(shù)本身,因此此時(shí)的bar()其實(shí)是一個(gè)不帶任何修飾的函數(shù)調(diào)用。
六、默認(rèn)綁定
如果上面三種綁定方法都不是的話,使用默認(rèn)綁定。如果在嚴(yán)格模式下,就綁定到 undefined ,否則綁定到全局對(duì)象。
- 在全局范圍內(nèi)聲明的變量,就是同名全局對(duì)象屬性的同義詞
function foo() {
console.log( this );
console.log( this.a );
}
var a = 2;
foo();// 2
- 在嚴(yán)格模式下,全局對(duì)象不符合默認(rèn)綁定的條件,因此將this設(shè)置為undefined
function foo() {
"use strict";
console.log( this.a );
}
var a = 2;
foo(); // TypeError: `this` is `undefined`
- 這個(gè)嚴(yán)格模式的作用區(qū)域,并沒有在foo中。
function foo() {
console.log( this.a );
}
var a = 2;
(function(){
"use strict";
foo(); // 2
})();
注意:有些調(diào)用可能在無(wú)意中使用默認(rèn)綁定規(guī)則。如果想保護(hù)全局對(duì)象,可以創(chuàng)建一個(gè)空對(duì)象,比如 Object.create(unll)。
七、ES6中箭頭函數(shù)
ES6中箭頭函數(shù)并不會(huì)使用四種標(biāo)準(zhǔn)的綁定規(guī)則,而是根據(jù)當(dāng)前的詞法作用域來(lái)決定this
var obj = {
say: function () {
setTimeout(() => {
// this指向obj,箭頭函數(shù)是根據(jù)當(dāng)前的詞法作用域來(lái)決定this。
console.log(this == obj);
}, 0)
}
}
obj.say();