在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 Operator在GetValue
起作用之前,在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/