各種 this 常常令人非常迷惑烹笔,至今只能理解簡單的情況,對于復(fù)雜的情況 this 傳來傳去抛丽,綁來綁去谤职。。亿鲜。還是會暈允蜈,不能透徹的理解冤吨。
this is neither a reference to the function itself, nor is it a reference to the function's lexical scope.
this is actually a binding that is made when a function is invoked, and what it references is determined entirely by the call-site where the function is called.
this 既不指向函數(shù),也不指向函數(shù)的 scope, 而是在函數(shù)執(zhí)行時動態(tài)綁定到所處的上下文饶套。
this 到底綁定到什么漩蟆,有 4 種基本的情況:
Default Binding
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 2
this 默認會綁定到 global 對象
function foo() {
"use strict";
console.log( this.a );
}
var a = 2;
foo(); // TypeError: `this` is `undefined`
只有在非嚴格模式下才允許 this 綁定到 global, 嚴格模式下不允許綁定到 global
Implicit Binding 隱式綁定
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
用一個對象 obj 去調(diào)用函數(shù),這時 this 就綁定到函數(shù)所在的對象
Explicit Binding 顯示綁定
function foo() {
console.log( this.a );
}
var obj = {
a: 2
};
foo.call( obj ); // 2
通過 call 或 apply 顯示調(diào)用一個函數(shù)并傳遞一個對象進去妓蛮,這時 this 就綁定到傳入的對象上怠李。這種情況最好理解。
new Binding
function foo(a) {
this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2
當(dāng)用 new 調(diào)用一個函數(shù)時主要做了下面4件事
- a brand new object is created
- the newly constructed object is [[Prototype]]-linked
- the newly constructed object is set as the this binding for that function call
- unless the function returns its own alternate object, the new-invoked function call will automatically return the newly constructed object.
當(dāng)用 new 調(diào)用一個函數(shù)時蛤克,底層默認會新建一個對象捺癞,this 會綁定到這個新建的對象上。默認函數(shù)會返回這個新建的對象构挤,當(dāng)然也可以返回其它的對象髓介。
Determining the this binding for an executing function requires finding the direct call-site of that function. Once examined, four rules can be applied to the call-site, in this order of precedence:
Called with new? Use the newly constructed object.
Called with call or apply (or bind)? Use the specified object.
Called with a context object owning the call? Use that context object.
Default: undefined in strict mode, global object otherwise.
總結(jié)下來就是找到函數(shù)調(diào)用點,依次看看是否符合以上 4 條規(guī)則
- 如果用 new 調(diào)用筋现, this 綁定到函數(shù)新建的對象上
- 顯示調(diào)用直接綁定到傳入的對象上
- 通過對象調(diào)用唐础,綁定到函數(shù)所在的對象上
- 默認綁定到 global 對象
Lexical this
function foo() {
// return an arrow function
return () => {
// `this` here is lexically adopted from `foo()`
console.log( this.a );
};
}
var obj1 = {
a:100
};
var a = 200;
foo.call(obj1)(); // 100
arrow-functions adopt the this binding from the enclosing (function or global) scope.
ES6 的 => 函數(shù)中的 this 會綁定到它所在的 scope 的 this。這里就是 foo 的 this矾飞。