前言
前端程式設計對於this
再熟悉不過了,今日來個老調重彈溫故知新,肯定有很多大佬已經完全吃透了this
原理,敬請出門左拐。對於理解this
似懂非懂的同學可以借鑑一波
1.this描述
this
指的是當前執行環境上下文,只要牢牢抓住這一點就能找到this
的根源,this.function
、this.property
就能準確定位實際物件。
2.this繫結規則
window 繫結
function sayAge () {
console.log(this.age);
}
var user = {
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
的繫結物件。