譯者按JavaScript的this
和Java等面向?qū)ο笳Z言中的this
大不一樣凯正,bind()
、call()
和apply()
函數(shù)更是將this
的靈活度進一步延伸秸抚。
為了保證可讀性速和,本文采用意譯而非直譯。另外耸别,本文版權(quán)歸原作者所有健芭,翻譯僅用于學(xué)習(xí)。
如果對JavaScript的關(guān)鍵字this
理解不夠深刻秀姐,有時候會掉入意想不到的坑。在這里我們總結(jié)了5條通用規(guī)則來幫助你判斷this
到底指向什么若贮。雖然沒有囊括所有的情況省有,但日常大部分情況都可以使用這些規(guī)則來正確推斷痒留。
-
this
的值通常是由所在函數(shù)的執(zhí)行環(huán)境決定,也就是說要看函數(shù)是如何被調(diào)用的蠢沿; - 同一個函數(shù)每一次調(diào)用伸头,
this
都可能指向不同的對象;
全局對象 (Global Object)
打開Chrome瀏覽器開發(fā)者面板(Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J),并且輸入:
console.log(this);
看看輸出了什么舷蟀?
// Window {}
window
對象恤磷! 因為在全局作用域下,this
指向全局對象野宜。在瀏覽器中全局對象就是window
對象扫步。
為了讓你更加清楚理解為什么this
會指向window
對象,我們來看另外一個例子:
var myName = 'Brandon';
我們可以通過在控制臺輸入myName
來訪問其值:
myName
// 輸出 'Brandon'
其實匈子,所有在全局定義的變量都綁定到window
對象河胎。我們來做如下測試:
window.myName
// 輸出 'Brandon'
window.myName === myName
// 輸出 true
現(xiàn)在我們將this
放到函數(shù)內(nèi)部,看看有何效果虎敦。
function test(){
return this;
}
test();
你會發(fā)現(xiàn)this
依然指向全局的window
對象游岳。因為this
關(guān)鍵字沒有處于一個聲明的對象內(nèi)部,默認(rèn)指向全局window
對象其徙。這一點可能對于大部分初學(xué)者來說有點難以理解胚迫。當(dāng)讀完這篇文章,你就會豁然開朗唾那。
注意:如果在strcit
模式下访锻,上面的例子中this
為undefined
。
聲明的對象 (Declared Object)
當(dāng)this
關(guān)鍵字在一個聲明對象內(nèi)部使用通贞,其值會被綁定到調(diào)用該this
的函數(shù)的最近的父對象朗若。我們用例子來說明這個問題:
var person = {
first: 'John',
last: 'Smith',
full: function() {
console.log(this.first + ' ' + this.last);
}
};
person.full();
// 輸出 'John Smith'
在被聲明的對象person
中的full
函數(shù)里面使用了this
, 那么調(diào)用this
的full
函數(shù)的最近的父對象就是person
, 因此,this
指向person
昌罩。
為了更好的描述this
實際上是指向person
對象的哭懈,你可以拷貝如下代碼到瀏覽器控制臺,將this
打印出來茎用。
var person = {
first: 'John',
last: 'Smith',
full: function() {
console.log(this);
}
};
person.full();
// 輸出 Object {first: "John", last: "Smith", full: function}
我們接下來看一個更復(fù)雜的例子:
var person = {
first: 'John',
last: 'Smith',
full: function() {
console.log(this.first + ' ' + this.last);
},
personTwo: {
first: 'Allison',
last: 'Jones',
full: function() {
console.log(this.first + ' ' + this.last);
}
}
};
在這里我們有嵌套的對象遣总,在這個時候,this
分別指向誰呢轨功? 我們將其打印出來看一看:
person.full();
// 輸出 'John Smith'
person.personTwo.full();
// 輸出 'Allison Jones'
你會發(fā)現(xiàn)滿足我們前面所描述的規(guī)則:其值會被綁定到調(diào)用this
的函數(shù)的最近的父對象旭斥。
new
關(guān)鍵字
當(dāng)使用new
關(guān)鍵字構(gòu)建一個新的對象,this
會綁定到這個新對象古涧。我們來看一個例子:
function Car(make, model) {
this.make = make;
this.model = model;
};
根據(jù)第一條規(guī)則垂券,你可能會推斷this
指向全局對象。但是如果我們使用new
關(guān)鍵字來聲明一個新的變量羡滑,Car
函數(shù)中的this
將會綁定一個新的空對象菇爪,然后初始化this.make
和this.model
的值算芯。
var myCar = new Car('Ford', 'Escape');
console.log(myCar);
// 輸出 Car {make: "Ford", model: "Escape"}
call
, bind
, 和apply
我們可以顯示的在call()
,bind()
凳宙,apply()
中設(shè)置this
的綁定對象熙揍。這三個函數(shù)很類似,但是我們需要注意它們微小的區(qū)別氏涩。
我們來看一個例子:
function add(c, d) {
console.log(this.a + this.b + c + d);
}
add(3,4);
// 輸出 NaN
add
函數(shù)輸出NaN
, 因為this.a
和this.b
未定義届囚。
現(xiàn)在我們引入對象,并且使用call()
和apply()
來調(diào)用:
function add(c, d) {
console.log(this.a + this.b + c + d);
}
var ten = {a: 1, b: 2};
add.call(ten, 3, 4);
// 輸出 10
add.apply(ten, [3,4]);
// 輸出 10
當(dāng)我們使用add.call()
是尖,第一個參數(shù)是this
需要綁定的對象意系,剩下的是add
函數(shù)本來的參數(shù)。
因此析砸,this.a
指向ten.a
,this.b
指向ten.b
昔字。add.apply()
也類似,除了第二個參數(shù)是一個數(shù)組首繁,用于存儲add
函數(shù)的參數(shù)作郭。
bind()
函數(shù)和call()
類似,但是bind()
函數(shù)不會立即被調(diào)用弦疮。bind()
函數(shù)會返回一個函數(shù)夹攒,并且將this
綁定好。接下來我們來用例子來幫助理解bind()
函數(shù)的應(yīng)用場景:
var small = {
a: 1,
go: function(b,c,d){
console.log(this.a+b+c+d);
}
}
var large = {
a: 100
}
執(zhí)行:
small.go(2, 3, 4);
// 輸出 10
如果我們想使用large.a
的值胁塞,而不是small.a
呢咏尝? 我們可以使用call/apply
:
small.go.call(large, 2, 3, 4);
// 輸出 109
但是,如果我們現(xiàn)在還不知道這三個參數(shù)應(yīng)該傳入什么值啸罢,應(yīng)該怎么辦呢编检? 我們可以使用bind
:
var bindTest = small.go.bind(large, 2);
如果我們將bindTest
在控制臺下打印出來,我們會看到:
console.log(bindTest);
// 輸出 function (b,c,d){console.log(this.a+b+c+d);}
注意:該函數(shù)已經(jīng)將this
綁定到large
對象扰才,并且傳入了第一個參數(shù)b
允懂。所以,我們接下來是需要傳入余下的參數(shù)即可:
bindTest(3, 4);
// 輸出 109
箭頭函數(shù)(=>)
因為需要很大的篇幅衩匣,我們會專門寫一篇博客來介紹蕾总。
結(jié)論
當(dāng)你讀完這篇博客,你應(yīng)該可以理解大多數(shù)情況下this
指向的對象琅捏。
接下來我們來總結(jié)一下:
-
this
的值通常是由當(dāng)前函數(shù)的執(zhí)行環(huán)境所決定生百; - 在全局作用域,
this
指向全局對象 (window
對象)柄延; - 當(dāng)使用
new
關(guān)鍵字聲明蚀浆,this
指向新建對象; - 我們可以使用
call()
,bind()
,apply()
來設(shè)置this
; - 箭頭函數(shù)不會綁定
this
蜡坊。
關(guān)于Fundebug
Fundebug專注于JavaScript杠输、微信小程序赎败、微信小游戲秕衙、支付寶小程序、React Native僵刮、Node.js和Java實時BUG監(jiān)控据忘。 自從2016年雙十一正式上線,F(xiàn)undebug累計處理了7億+錯誤事件搞糕,得到了Google勇吊、360、金山軟件窍仰、百姓網(wǎng)等眾多知名用戶的認(rèn)可汉规。歡迎免費試用!
版權(quán)聲明:
轉(zhuǎn)載時請注明作者Fundebug**以及本文地址:
https://blog.fundebug.com/2017/05/17/javascript-this-for-beginners