以下两个语句之间有什么区别(在全局窗口的上下文中)?
(function() { return a; } )(); // ReferenceError: a is not defined
(function(a) { return a; } )(); // returns undefined
Run Code Online (Sandbox Code Playgroud)
我认为它与以下内容有关:
a; // ReferenceError: a is not defined
window.a; // undefined
Run Code Online (Sandbox Code Playgroud)
看起来第二个函数在范围链中上升并在全局窗口范围结束,其中a不是窗口的属性并因此返回undefined.但是,第一个功能不应该做同样的事情并返回undefined吗?
我发现这个关于未定义与未定义的SO问题,但它似乎更多地应用于变量而不是窗口范围中的属性.
我认为这是一个常见的陷阱和一个重要问题,如果您正在阅读本文并且任何内容都不清楚,请在评论中告诉我.
a; - 将抛出引用错误,因为它试图访问未定义的变量
function() { return a; } )(); - 这与上面的情况完全相同,它是对未定义变量的访问
object.a - 将返回undefined,我们不是试图在这里访问一个未定义的变量,而是一个已知对象的属性,这是不同的
(function(a) { return a; } )();- 将返回undefined,a这里是一个参数而不是未定义的变量,它将被赋予实际的语言原始值类型undefined.
让我们深入挖掘一下吧?
让我们看看语言规范对所有这些情况的评价:
规范说明:
如果是IsUnresolvableReference(V),则抛出ReferenceError异常.
规范说明:
IsUnresolvableReference(V).返回真,如果基值是不确定的和虚假的,否则.
这就是为什么会发生以下情况:
a; // ReferenceError: a is not defined
Run Code Online (Sandbox Code Playgroud)
由于未定义基值,因此会根据规范指定引发引用错误.
在一个对象中,base不是未定义的(它是对象)所以它一切都很好并且不会抛出任何错误.这样解决了:
当V是具有基本基值的属性引用时,GetValue使用以下[[Get]]内部方法.使用base作为其值并使用属性P作为其参数调用它.采取以下步骤:
设O为ToObject(base).
设desc是调用属性名为P的O的[[GetProperty]]内部方法的结果.
如果未定义desc,则返回undefined.
这就是你看到的原因:
window.a; // undefined
Run Code Online (Sandbox Code Playgroud)
另一种情况 - 参数完全不同,参数存在,但其值设置为原始值类型undefined.现有和未定义之间存在差异而不存在:)
这在这里指定:
如果n大于argCount,则让v为undefined,否则让v为args的第n个元素的值.
这就是为什么:
(function(a) { return a; } )(); // returns undefined
Run Code Online (Sandbox Code Playgroud)