天天看點

《你不知道的JavaScript》整理(二)——this一、調用位置二、綁定規則三、優先級四、綁定例外

當一個函數被調用時,會建立一個活動記錄(執行上下文)。

這個記錄會包含函數在哪裡被調用(調用棧)、函數的調用方法、傳入的參數等資訊。

this就是記錄的其中一個屬性,會在函數執行的過程中用到。

this既不指向函數自身也不指向函數的作用域。

this實際上是在函數被調用時發生的綁定,它指向什麼完全取決于函數在哪裡被調用。

你必須找到調用位置,然後判斷需要應用下面四條規則中的哪一條。

1)預設綁定

最常用的函數調用類型:獨立函數調用。可以把這條規則看作是無法應用其他規則時的預設規則。

2)隐式綁定

隐式綁定的規則是調用位置是否有上下文對象,或者說是否被某個對象擁有或者包含。

但有時候會出現隐式丢失。

雖然bar是obj.foo的一個引用,但是實際上,它引用的是foo函數本身。

是以此時的bar()其實是一個不帶任何修飾的函數調用,應用了預設綁定。

3)顯式綁定

使用函數的call(..)和apply(..)方法。

在很多庫中經常能看到bind方法,這是一種硬綁定,一種顯式的強制綁定,下面是一種bind實作。

4)new綁定

使用new來調用函數,或者說發生構造函數調用時,會自動執行下面的操作:

1. 建立(或者說構造)一個全新的對象。

2. 這個新對象會被執行[[原型]]連接配接。

3. 這個新對象會綁定到函數調用的this。

4. 如果函數沒有傳回其他對象,那麼new表達式中的函數調用會自動傳回這個新對象。

預設綁定的優先級是四條規則中最低的。

1)顯式綁定優先級比隐式綁定要更高

2)new綁定比隐式綁定優先級高

3)new綁定會修改顯示綁定中this

4)判斷this

1. 函數是否在new中調用(new綁定)?如果是的話this綁定的是新建立的對象。

2. 函數是否通過call、apply(顯式綁定)或者硬綁定調用?如果是的話,this綁定的是指定的對象。

3. 函數是否在某個上下文對象中調用(隐式綁定)?如果是的話,this綁定的是那個上下文對象。

4. 如果都不是的話,使用預設綁定。如果在嚴格模式下,就綁定到undefined,否則綁定到全局對象。

1)被忽略的this

如果你把null或者undefined作為this的綁定對象傳入call、apply或者bind。

這些值在調用時會被忽略,實際應用的是預設綁定規則。

2)間接引用

你有可能(有意或者無意地)建立一個函數的“間接引用”。

在這種情況下,調用這個函數會應用預設綁定規則。

指派表達式p.foo = o.foo的傳回值是目标函數的引用,是以調用位置是foo()而不是p.foo()或者o.foo()。

3)軟綁定

如果可以給預設綁定指定一個全局對象和undefined以外的值。

那就可以實作和硬綁定相同的效果,同時保留隐式綁定或者顯式綁定修改this的能力。

可以通過一種被稱為軟綁定的方法來實作我們想要的效果。

軟綁定版本的foo()可以手動将this綁定到obj2或者obj3上。

但如果應用預設綁定,則會将this綁定到obj。

    本文轉自 咖啡機(K.F.J)   部落格園部落格,原文連結:http://www.cnblogs.com/strick/p/5813749.html,如需轉載請自行聯系原作者

繼續閱讀