JavaScript This 的六道坎

發表於2017-02-09

鑑於this風騷的運作方式,對this的理解是永不過時的話題,本文試圖通過將其大卸六塊來釘住這個磨人的妖精。

首先

this is all about context.

this說白了就是找大佬,找擁有當前上下文(context)的物件(context object)。

大佬可以分為六層,層數越高權力越大,this只會認最大的。

第一層:世界盡頭

權力最小的大佬是作為備胎的存在,在普通情況下就是全域性,瀏覽器裡就是window;在use strict的情況下就是undefined

第二層:點石成金

第二層大佬說白了就是找這個函式前面的點.

如果用到this的那個函式是屬於某個 context object 的,那麼這個 context object 繫結到this

比如下面的例子,bossreturnThis的 context object ,或者說returnThis屬於boss

下面這個例子就要小心點咯,能想出答案麼?

答案是boss1window哦,猜對了嗎。

只要看使用this的那個函式。

boss2.returnThis裡,使用this的函式是boss1.returnThis,所以this繫結到boss1

boss3.returnThis裡,使用this的函式是returnThis,所以this繫結到備胎。

要想把this繫結到boss2怎麼做呢?

沒錯,只要讓使用this的函式是屬於boss2就行。

第三層:指腹為婚

第三層大佬是Object.prototype.callObject.prototype.apply,它們可以通過引數指定this。(注意this是不可以直接賦值的哦,this = 2會報ReferenceError。)

第四層:海誓山盟

第四層大佬是Object.prototype.bind,他不但通過一個新函式來提供永久的繫結,還會覆蓋第三層大佬的命令。

第五層:內有乾坤

一個比較容易忽略的會繫結this的地方就是new。當我們new一個函式時,就會自動把this繫結在新物件上,然後再呼叫這個函式。它會覆蓋bind的繫結。

第六層:軍令如山

最後一個法力無邊的大佬就是 ES2015 的箭頭函式。箭頭函式裡的this不再妖豔,被永遠封印到當前詞法作用域之中,稱作 Lexical this ,在程式碼執行前就可以確定。沒有其他大佬可以覆蓋。

這樣的好處就是方便讓回撥函式的this使用當前的作用域,不怕引起混淆。

所以對於箭頭函式,只要看它在哪裡建立的就行。

如果對 V8 實現的詞法作用域感興趣可以看看這裡

下面這種奇葩的使用方式就需要注意:

如果你不知道最後為什麼會是 boss2,繼續理解“對於箭頭函式,只要看它在哪裡建立”這句話。

參考

  1. Mozilla Developer Network
  2. Kyle Simpson, this & object prototypes
  3. Axel Rauschmayer, Speaking JavaScript

相關文章