以下是知乎上的兩個回答,分別從宏觀和微觀的角度分析這個原因。
1.微觀角度
鏈接:https://www.zhihu.com/question/21958425/answer/19858492
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
這個問題的官方答案就是,ES3時代設計上就是故意如此. 但是准確的表述並不和 匿名函數直接關聯. 只是匿名函數符合函數調用時的某個規則而已.
因為一些生產環境代碼經常無意中進入某種陷阱或帶來一些代碼的邏輯性斷層. 導致ES5時代,在嚴格模式中.把原有this的行為做了修正.
現在我來說說那個所謂某個規則是什么..
准確來說,我們拋開 call,和apply . 那么影響this 的就是 Property accessor 語法.
即 obj.foo() ; 屬性訪問語法,即函數調用運算符"()" 左邊部分. 會獲取一個 base 為obj 的 referenceType . 然后進行函數調用運算. 則referenceType.base 會為該函數執行環境的this 提供引用.
你想消除referenceType 很簡單 (1,obj.foo)() 這樣就行了. 因為 分組運算符的加入.導致提前對 referenceType進行getValue 操作. 直接拿到函數對象進行函數調用運算.導致提供給該函數執行環境關聯的this值是null. ES3明確表述,當此類情形發生時.則把global作為 this. ES5 的嚴格模式則修正了這一規則.
忘了補充下,你所謂的匿名函數在函數調用時是什么. 舉個例子.
(function(){this === global}());
就拿常用的例子來說. 外層分組運算符的作用是讓 匿名函數表達式合法. 因 javascript 語法限制. 禁止函數表達式中, function 關鍵字出現在表達式的第一個token位置. so. 必須借助其他輔助語法來完成所謂匿名函數的立即調用..比如 賦值表達式,逗號運算等等.
顯然匿名函數解釋執行的結果不是一個referenceType .但是規則中有表述,當不是referenceType時. 仍然把null (undefined-SE5) 作為this 提供給該函數執行環境.
那么你看到上面所謂匿名函數調用(函數立即調用表達式). 和平時的 函數直接調用有啥區別么?
var fn = function(){this === null};
fn();
答案是有. fn(); 這玩意其實解釋執行fn時還是有referenceType .但是其base 是ES3世道的變量對象. 此時仍然把null 作為this. 然后又符合那種規則了.
2.宏觀角度
作者:
從作用域和調用鏈方面看就很好理解了, 匿名函數是一個沒有指針的全局變量,那么它的this指向的就是全局 就是window對象。這並不是設計缺陷,這種調用很安全,通過window並不能找到這個匿名函數,因為匿名函數沒有指針。
