在Chrome和Firefox中,

typeof foo

评估为'undefined'


typeof (function() { return foo; })()

引发错误:
ReferenceError: foo is not defined

这破坏了我对表达的可替代性的观念! 到现在为止,我还不知道foo(function() { return foo; })()不相同的条件。

这是标准行为吗?如果是这样,引用ECMAScript标准的相关部分会很有帮助。

编辑:

另一个例子:
typeof (foo)
typeof (foo + 0)

我希望(foo)(foo + 0)引发错误。

但是第一个没有错误。第二个呢。

最佳答案

基本上, typeof 运算符检查变量¹是否不可解析,并返回"undefined"。也就是说,在到达引发未声明变量¹的 typeof 算法之前,GetValue返回未声明变量¹的定义值。

引用ECMAScript 5.1 § 11.4.3 The typeof Operator(添加了重点):



另一方面,return statement像大多数从标识符读取值的运算符和语句一样,将始终调用 GetValue ,后者抛出无法解析的标识符(未声明的变量)。引用ECMAScript 5.1 § 8.7.1 GetValue (V)(添加了重点):



现在,分析代码:

typeof (function() { return foo; })()

该代码将实例化一个函数对象,然后执行它,然后typeof才对函数的返回值进行操作(函数调用将precedence替换为typeof运算符)。

因此,在可以评估return操作之前,代码在评估IIFE的typeof语句时抛出。

一个类似但更简单的示例:
typeof (foo+1)

typeof之前评估加法。当Addition OperatorGetValue起作用之前,在foo上调用typeof时,这将引发错误。

现在:
typeof (foo)

不会引发错误,因为grouping operator(括号)本身并不“评估”任何内容,它只是强制优先级。更具体地说,分组运算符不调用GetValue。在上面的示例中,它返回一个(不可解析的)引用。

annotated ES5.1 spec甚至添加了关于此的注释:



N.B. 我写这个答案的重点是提供一个简单易懂的解释,使技术术语降至最低,同时仍要足够清晰,并提供所要求的ECMAScript标准引用,我希望这对那些苦苦挣扎的开发人员是有用的资源。了解typeof运算符。

¹为了易于理解,使用了“变量”一词。一个更正确的术语是标识符,它不仅可以通过变量声明,而且可以通过函数声明,形式参数,调用函数(arguments),with / catch块,将属性分配给全局对象let引入Lexical Environment中。和const语句(ES6),可能还有其他几种方式。

关于javascript - 为什么typeof有时只抛出ReferenceError?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24150713/

10-16 17:57