一输钩、this是什么?
this是指包含它的函數(shù)作為方法被調(diào)用時所屬的對象仲智。
二买乃、由new調(diào)用(new綁定),綁定到新創(chuàng)建的對象
new表達式:
function foo(a) {
this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2
三钓辆、由call 剪验、apply、bind 調(diào)用(顯示綁定)前联,綁定到指定的對象
顯示綁定:可以直接指定this的綁定對象功戚,例如call()、apply()似嗤。
1.call ( 傳的this啸臀,參數(shù)用逗號隔開 )
2.aplay(傳的this,【參數(shù)用數(shù)組形式】)
3.bind 返回的是一個新的函數(shù)烁落,必須調(diào)用它才會被執(zhí)行乘粒,它的參數(shù)和 call 一樣。
注意:
如果第一個參數(shù)傳的是null伤塌,和undefined 灯萍,this會指向window;
如果是number每聪、string旦棉、boolean會轉(zhuǎn)向包裝類型。
四熊痴、由上下文調(diào)用(隱式綁定)他爸,綁定到那個上下文對象
隱式綁定:會把函數(shù)調(diào)用的this綁定到這個上下文對象。
注意:隱式綁定的函數(shù)如果丟失了綁定的對象果善,就會應用默認綁定,從而吧this綁定到全局對象或者undefined上系谐,取決于是否是嚴格模式巾陕。
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 來查找上下文調(diào)用時this的指向
call-site:調(diào)用位置晾匠,函數(shù)在代碼中被調(diào)用的位置(不是聲明的位置)。
call-stack:調(diào)用棧梯刚,就是為了到達當前執(zhí)行位置所調(diào)用的所有函數(shù)凉馆。可以從調(diào)用棧中分析出真正的調(diào)用位置亡资,因為它決定了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的一個引用,它引用的是foo函數(shù)本身锥腻,因此此時的bar()其實是一個不帶任何修飾的函數(shù)調(diào)用嗦董。
六、默認綁定
如果上面三種綁定方法都不是的話瘦黑,使用默認綁定京革。如果在嚴格模式下,就綁定到 undefined 幸斥,否則綁定到全局對象匹摇。
- 在全局范圍內(nèi)聲明的變量,就是同名全局對象屬性的同義詞
function foo() {
console.log( this );
console.log( this.a );
}
var a = 2;
foo();// 2
- 在嚴格模式下甲葬,全局對象不符合默認綁定的條件廊勃,因此將this設置為undefined
function foo() {
"use strict";
console.log( this.a );
}
var a = 2;
foo(); // TypeError: `this` is `undefined`
- 這個嚴格模式的作用區(qū)域,并沒有在foo中演顾。
function foo() {
console.log( this.a );
}
var a = 2;
(function(){
"use strict";
foo(); // 2
})();
注意:有些調(diào)用可能在無意中使用默認綁定規(guī)則供搀。如果想保護全局對象,可以創(chuàng)建一個空對象钠至,比如 Object.create(unll)葛虐。
七、ES6中箭頭函數(shù)
ES6中箭頭函數(shù)并不會使用四種標準的綁定規(guī)則棉钧,而是根據(jù)當前的詞法作用域來決定this
var obj = {
say: function () {
setTimeout(() => {
// this指向obj,箭頭函數(shù)是根據(jù)當前的詞法作用域來決定this屿脐。
console.log(this == obj);
}, 0)
}
}
obj.say();