为什么引用未声明的变量会引发引用异常,而引用未声明的属性却不会?

Why does referencing undeclared variables throw a reference exception but referencing undeclared properties doesn't?

Mozilla says that variables are properties of the global object。如果对象具有未定义的 属性,则尝试访问它不会创建引用异常 - 它只是 returns 未定义 属性。

如果存在这样的全局对象 - 那么为什么访问其不存在的属性(即:变量)会产生引用错误?这两种情况到底有什么区别?

示例:

console.log(x) //x is not declared -> reference error


var x = new Object();
console.log(x.property); //console.log: undefined

tl;dr: 访问变量的 方式 造成了所有差异,而不是它的存储方式。


首先是一些背景:

基本上变量有两种方式"stored"。

declarative environment 中,变量存储在用户代码无法访问的内部数据结构中。

object environment 中,变量存储为用户代码可访问对象的属性。全局环境恰好是一个对象环境(它比这复杂一点,但让我们保持简单)。因此全局变量是全局对象的属性。


那么为什么访问一个不存在的全局变量会抛出错误呢?因为变量如何存储相关,只有变量如何访问.

foowindow.foo 只是访问全局变量的两种不同方式。

评估变量的语言规则 (foo) 明确指出,如果变量不存在,则抛出引用错误(同样,无论它如何存储)。*

The language rules 用于评估 属性 访问权限 (window.foo) 表示如果 属性 不存在,则应返回 undefined

如果您考虑一下,从一致性的角度来看,这更有意义。访问 foo 应该有相同的结果,无论变量是存储在声明环境还是对象环境。


*:更准确地说:是 GetValue 函数导致抛出错误。 GetValue 在解析变量时几乎无处不在(例外是 typeof 和分组运算符 (...))。