我认为这是一个常见的陷阱和一个重要的问题,如果您正在阅读本文并且有任何不清楚的地方,请在评论中告诉我。
简而言之
a;
- 将抛出一个引用错误,因为它试图访问一个未定义的变量
function() { return a; } )();
- 这与上面的情况完全一样,它是对未定义变量的访问
object.a
- 将返回未定义,我们在这里不是试图访问未定义的变量,而是已知对象的属性,这是不同的
(function(a) { return a; } )();
- 将返回未定义,a
这里是一个参数而不是未定义变量,它将被分配实际的语言原始值类型undefined
。
让我们再深入一点好吗?
规格
让我们看看语言规范对所有这些情况的看法:
未声明的变量引用
规范在这里指出:
如果 IsUnresolvableReference(V),则抛出ReferenceError异常。
该规范指出:
IsUnresolvableReference(V)。如果基值未定义,则返回true ,否则返回false。
这就是为什么会发生以下情况:
a; // ReferenceError: a is not defined
由于未定义基值,因此会引发规范指定的引用错误。
未声明的对象属性
在一个对象中,base 不是未定义的(它是对象),所以一切都很好并且不会引发错误。它是这样解决的:
当 V 是具有原始基值的属性引用时,GetValue 使用以下 [[Get]] 内部方法。使用 base 作为 this 值并使用属性 P 作为参数来调用它。采取以下步骤:
令 O 为 ToObject(base)。
令 desc 为使用属性名称 P 调用 O 的 [[GetProperty]] 内部方法的结果。
如果 desc 未定义,则返回undefined。
这就是为什么你会看到:
window.a; // undefined
功能参数
另一种情况——参数则完全不同,参数存在,但其值设置为未定义的原始值类型。存在与未定义和不存在之间存在差异:)
这是在这里指定的:
如果 n 大于 argCount,则令 v 未定义,否则令 v 为 args 的第 n 个元素的值。
这就是为什么:
(function(a) { return a; } )(); // returns undefined