在 Chrome 和 Firefox 中,
typeof foo
计算为 'undefined'
。
但是
typeof (function() { return foo; })()
抛出一个错误:
ReferenceError: foo is not defined
这破坏了我对表达式可替代性的看法!直到现在,我还不知道 foo
和 (function() { 返回的条件foo; })()
不一样。
这是标准行为吗?如果是这样,引用 ECMAScript 标准的相关部分会很有帮助。
编辑:
另一个例子:
typeof (foo)
typeof (foo + 0)
我本以为 (foo)
和 (foo + 0)
会抛出错误。
但是第一个没有错误;第二个是。
最佳答案
基本上,typeof
运算符检查变量¹ 是否不可解析并返回 "undefined"
。也就是说,typeof
在到达 GetValue
之前返回未声明变量的定义值。抛出未声明变量的算法¹。
引用 ECMAScript 5.1 § 11.4.3 The typeof Operator (强调):
11.4.3 The typeof Operator
The production UnaryExpression :
typeof
UnaryExpression is evaluated as follows:
另一方面,return statement -- 像大多数从标识符中读取值的运算符和语句一样 -- 将始终调用 GetValue
这会引发无法解析的标识符(未声明的变量)。引用 ECMAScript 5.1 § 8.7.1 GetValue (V) (强调):
8.7.1 GetValue (V)
- If Type(V) is not Reference, return V.
- Let base be the result of calling GetBase(V).
- If IsUnresolvableReference(V), throw a
ReferenceError
exception.
现在,分析代码:
typeof (function() { return foo; })()
此代码将实例化一个函数对象,执行它,然后 typeof
将对函数的返回值进行操作(函数调用在 typeof
运算符上采用 precedence) .
因此,代码在评估 IIFE 的 return
语句时抛出,然后才能评估 typeof
操作。
一个类似但更简单的例子:
typeof (foo+1)
加法在 typeof
之前求值。这将在 Addition Operator 时抛出错误。在 typeof
发挥作用之前,在 foo
上调用 GetValue
。
现在:
typeof (foo)
不会像 grouping operator 那样抛出错误(括号)本身并不“评估”任何东西,它只是强制优先。更具体地说,分组运算符不调用 GetValue
。在上面的示例中,它返回一个(无法解析的)Reference。
annotated ES5.1 spec甚至添加了关于此的注释:
NOTE This algorithm does not apply
GetValue
to the result of evaluating Expression. The principal motivation for this is so that operators such asdelete
andtypeof
may be applied to parenthesised expressions.
N.B. 我写这个答案的重点是提供一个简单易懂的解释,将技术术语保持在最低限度,同时仍然足够清晰,并提供所需的 ECMAScript 标准引用,我希望对难以理解 typeof
运算符的开发人员来说是一个有用的资源。
¹ 使用术语“变量”是为了便于理解。更正确的术语是标识符,它可以被引入到 Lexical Environment 中。不仅通过变量声明,还通过函数声明、形参、调用函数(arguments
)、with
/catch
block 、赋值属性到全局对象、let
和 const
语句 (ES6),可能还有一些其他方式。
关于javascript - 为什么 typeof 只是有时抛出 ReferenceError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24150713/