前端之路——JS中的this繫結
預設繫結
在閱讀了<<你不知道的JavaScript 上卷>> 後, 對JavaScript中的 this 做一個簡要的總結.
無法應用其他規則時,this會繫結全域性作用域(非嚴格模式),或者繫結到undefined(嚴格模式)
function foo(){ console.log(this.a); } var a = 2; foo();//2在node下測試結果為undefined
"use strict"; function foo(){ console.log(this.a); } var a = 2; foo();//undefined在node下測試異常 TypeError: Cannot read property 'a' of undefined
隱式繫結
呼叫位置有上下文物件時,this會繫結為上下文物件
function foo(){ console.log(this.a); } var obj = { a: 22, foo: foo }; obj.foo();//22
隱式繫結時會出現繫結丟失,從而應用預設繫結
function foo(){ console.log(this.a); } var obj = { a: 22, foo: foo }; var a = 1; var bar = obj.foo; bar();//1 在node下測試結果為undefined
因為在把obj.foo賦值給bar後,bar實際指向的僅僅是foo,即丟失了上下文物件obj
顯式繫結
使用call()或apply()顯式改變上下文物件,從而改變this繫結。
function foo(){ console.log(this.a); } var obj = { a: 22 }; foo.call(obj);//22
使用顯式繫結依然無法解決繫結丟失的問題,因為call()和apply()實際上是在"執行"函式,在這一次執行的過程中,上下文物件是obj,脫離了這一次執行上下文,foo中的this就不再繫結到obj
function foo(){ console.log(this.a); } var obj = { a: 22 }; var a = 2; foo.call(obj);//22 foo();//2在node下測試結果為undefined
在顯式繫結的基礎上的硬繫結,就可以防止繫結丟失
function foo(){ console.log(this.a); } var bar = function(){ foo.call(obj); }; var obj = { a: 22 }; var obj2 = { a: 222 }; var obj3= { a: 2222, bar: bar }; var a = 2; bar();//22 obj3.bar();//22 bar.call(obj2);//22
對於bar而言的硬繫結,在其內部顯式繫結到了obj上,this就一直繫結到obj
new繫結
使用new來呼叫函式時,會執行以下操作:
- 構造一個全新物件
- 這個新物件會被執行原型連結
- 新物件會繫結到函式呼叫的this
- 如果函式沒有返回其他物件,那麼new表示式中的函式呼叫會自動返回這個新物件
function foo(a){ this.a = a; } var bar = new foo(22); console.log(bar.a);//22
優先順序
new繫結>顯式繫結>隱式繫結>預設繫結
箭頭函式中的this詞法
箭頭函式() => {}
中的this會預設繫結到箭頭函式所在函式作用域中的this。
function foo(a){ return () => console.log(this.a); } var obj = { a: 2 }; var obj2 = { a: 22 } var bar = foo.call(obj); bar.call(obj2);//2