匿名函数的this指向为什么是window?

时间:2023-01-09 19:37:03

 

以下是知乎上的两个回答,分别从宏观和微观的角度分析这个原因。

1.微观角度

作者:franky
链接: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?

 

从作用域和调用链方面看就很好理解了, 匿名函数是一个没有指针的全局变量,那么它的this指向的就是全局 就是window对象。这并不是设计缺陷,这种调用很安全,通过window并不能找到这个匿名函数,因为匿名函数没有指针。