JavaScript初學(xué)者必看“this”

譯者按JavaScript的this和Java等面向?qū)ο笳Z言中的this大不一樣凯正,bind()call()apply()函數(shù)更是將this的靈活度進一步延伸秸抚。

為了保證可讀性速和,本文采用意譯而非直譯。另外耸别,本文版權(quán)歸原作者所有健芭,翻譯僅用于學(xué)習(xí)。

如果對JavaScript的關(guān)鍵字this理解不夠深刻秀姐,有時候會掉入意想不到的坑。在這里我們總結(jié)了5條通用規(guī)則來幫助你判斷this到底指向什么若贮。雖然沒有囊括所有的情況省有,但日常大部分情況都可以使用這些規(guī)則來正確推斷痒留。

  1. this的值通常是由所在函數(shù)的執(zhí)行環(huán)境決定,也就是說要看函數(shù)是如何被調(diào)用的蠢沿;
  2. 同一個函數(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模式下访锻,上面的例子中thisundefined

聲明的對象 (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)用thisfull函數(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.makethis.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.athis.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é)一下:

  1. this的值通常是由當(dāng)前函數(shù)的執(zhí)行環(huán)境所決定生百;
  2. 在全局作用域,this指向全局對象 (window對象)柄延;
  3. 當(dāng)使用new關(guān)鍵字聲明蚀浆,this指向新建對象;
  4. 我們可以使用call(), bind(), apply()來設(shè)置this
  5. 箭頭函數(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驹吮,一起剝皮案震驚了整個濱河市针史,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碟狞,老刑警劉巖啄枕,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異族沃,居然都是意外死亡频祝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門脆淹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來常空,“玉大人,你說我怎么就攤上這事盖溺±觳冢” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵咐柜,是天一觀的道長兼蜈。 經(jīng)常有香客問我,道長拙友,這世上最難降的妖魔是什么为狸? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮遗契,結(jié)果婚禮上辐棒,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好漾根,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布泰涂。 她就那樣靜靜地躺著,像睡著了一般辐怕。 火紅的嫁衣襯著肌膚如雪逼蒙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天寄疏,我揣著相機與錄音是牢,去河邊找鬼。 笑死陕截,一個胖子當(dāng)著我的面吹牛驳棱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播农曲,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼社搅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乳规?” 一聲冷哼從身側(cè)響起形葬,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驯妄,沒想到半個月后荷并,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡青扔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年源织,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片微猖。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡谈息,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凛剥,到底是詐尸還是另有隱情侠仇,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布犁珠,位于F島的核電站逻炊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏犁享。R本人自食惡果不足惜余素,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望炊昆。 院中可真熱鬧桨吊,春花似錦威根、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至佑淀,卻和暖如春留美,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背渣聚。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工独榴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奕枝。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像瓶堕,于是被迫代替她去往敵國和親隘道。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容