再也不用被this苦惱了
前端程式設計對於this再熟悉不過了,今日來個老調重彈溫故知新,肯定有很多大佬已經完全吃透了this原理,敬請出門左拐。對於理解this似懂非懂的同學可以借鑑一波
1.this描述
this指的是當前執行環境上下文,只要牢牢抓住這一點就能找到this的根源,this.function、this.property就能準確定位實際物件。
2.this繫結規則
window 繫結
function sayAge () { console.log(this.age); } varuser = { name: 'ccy', age: 18 } sayAge()
輸出結果為undefined,仔細思考當前函式執行的上下文,其實等價於window.sayAge()
this預設繫結在window全域性物件上
隱式繫結
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo();
這段程式碼this繫結到了obj物件,當函式引用有上下文物件(context)時,隱式繫結規則會把this繫結到這個上下文物件
再看看隱式丟失問題
var bar=obj.foo; bar();
輸出undefined,因為此時執行上下文為全域性物件,沒有a屬性
顯式繫結
在分析隱式繫結時,必須將函式作為物件的屬性,從而將此物件繫結在函式的執行上下文,但想想是不是很麻煩,顯示繫結可解決此問題。
function foo() { console.log( this.a ); } var obj = { a:2 }; foo.call( obj );
用函式原型屬性 call、apply、bind都可以實現
Function.prototype.call=function(ctx,arg1,arg2,/*...*/argN){native code} Function.prototype.apply=function(ctx,arrys){native code} Function.prototype.bind=function(ctx){native code}
當然這些函式原型屬性都可以重寫以實現自己的需求,call和apply的區別僅僅在於第二個引數開始apply傳遞陣列,call是將引數一個個傳遞,call與bind的區別在於bind不能立即執行。
new 繫結
其實每當用 new 呼叫函式時,JavaScript 直譯器都會在底層建立一個全新的物件並把這個物件當做 this。如果用 new 呼叫一個函式,this 會自然地引用直譯器建立的新物件。
function User (name, age) { /* JavaScript 會在底層建立一個新物件 `this`,它會代理不在User 原型鏈上的屬性。 如果一個函式用 new 關鍵字呼叫,this 就會指向直譯器建立的新物件。 */ this.name = name this.age = age } var me = new User('ccy', 18)
如果要判斷一個執行中函式的this繫結,就需要找到這個函式的直接呼叫位置。找到之後就可以順序應用下面這四條規則來判斷this的繫結物件。
參考資料
ofollow,noindex">https://juejin.im/post/5b9f176b6fb9a05d3827d03f