今天前Leader在下班前發給我一道JavaScript的題目,看到感受很不錯,並且我開始的時候確實也理解錯了,以爲有必要拿出來說講,而且爲此我也作錯了地鐵,哈哈哈~
題目是這樣的:javascript
var length = 10; function fn() { console.log(this.length) }; var obj = { length: 5, method: function (fn) { fn(); arguments[0](); fn.call(obj, 12); } }; obj.method(fn, 1);
請問輸出是什麼,當時那手機看的時候給出了答案java
10 10 5
實際上並非如此,答案是:git
10 2 5
仔細分析了一下才知道緣由,首先介紹一下四種this的類型:github
默認綁定數組
隱式綁定app
顯示綁定函數
new綁定this
其中,默認綁定就是什麼都匹配不到的狀況下,非嚴格模式this
綁定到全局對象window
或者global
,嚴格模式綁定到undefined
;隱式綁定就是函數做爲對象的屬性,經過對象屬性的方式調用,這個時候this
綁定到對象;顯示綁定就是經過apply
和call
調用的方式;new綁定就是經過new
操做符時將this
綁定到當前新建立的對象中,它們的匹配有限是是從小到大的。
那麼如今來解釋一下:code
obj.method(fn, 1);
上述執行其實對應的是下面三條語句:對象
fn(); arguments[0](); fn.call(obj, 12);
經過將函數賦值給函數參數(fn
),而後調用fn
,這個時候能匹配到的this
類型就是第一條默認綁定,由於實在非嚴格模式下,因此this
綁定的是window
,固然首先輸出的是10
。
先解釋一下第三個,這個也很簡單,由於用了call
,因此實際匹配了顯示綁定
,因此當前this
綁定了obj
,那麼輸出的確定是2
。
下面着重解釋一下第二個,這個我當時理解成和第一次徹底同樣,但實際並非的,其實在JavaScript中數組算是一種特殊的對象(關於JavaScript對象的部分,我如今還在寫,下一篇就會出的),arguments[0]
其實就是經過對象的屬性去調用(數組的默認屬性類型是數值而普通對象的屬性類型是字符串),那麼如今其實運用的是規則2,this
被綁定到arguments
上,而arguments
確實存在一個length
屬性,而且值爲2(這個別告訴我你看不出來),因此輸出的確定就是2
啦。
可見《你不知道的JavaScript》這本書說的很對,之因此會在ES6出現箭頭函數,實質就像用詞法做用域代替this
,由於這個真的特別特別容易誤用和讓人誤解。
歡迎你們到個人我的博客看看,https://mrerhu.github.io ?