JavaScript中未定义与已定义的窗口属性

时间:2013-06-25 02:43:14

标签: javascript

以下两个语句之间有什么区别(在全局窗口的上下文中)?

(function() { return a; } )(); // ReferenceError: a is not defined
(function(a) { return a; } )(); // returns undefined

我认为它与以下内容有关:

  a; // ReferenceError: a is not defined
  window.a; // undefined

似乎第二个函数在范围链上移动并在全局窗口范围结束,其中a不是窗口的属性,因此返回undefined。但是第一个函数不应该也这样做并返回undefined吗?

我发现这个SO question关于未定义与未定义,但它似乎更多地应用于变量而不是窗口范围中的属性。

2 个答案:

答案 0 :(得分:6)

我认为这是一个常见的陷阱和一个重要问题,如果您正在阅读此内容并任何不清楚,请在评论中告诉我。

简而言之

  • a; - 会抛出引用错误,因为它试图访问未定义的变量

  • function() { return a; } )(); - 这与上面的情况完全相同,它可以访问未定义的变量

  • object.a - 将返回undefined,我们不是在这里尝试访问未定义的变量,而是已知对象的属性,这是不同的

  • (function(a) { return a; } )(); - 将返回undefined,a是一个参数,而不是未定义的变量,它将被分配实际的语言原始值类型undefined

让我们深入挖掘一下吗?

规范


让我们看看语言规范对所有这些案例的评价:

未声明的变量引用

规范说明here:

  

如果是IsUnresolvableReference(V),则抛出 ReferenceError 异常。

规范声明:

  

IsUnresolvableReference(V)。如果基值未定义,则返回 true ,否则返回 false

这就是为什么会发生以下情况:

a; // ReferenceError: a is not defined

由于未定义基值,因此会根据规范指定引发引用错误。

未声明的对象属性

在一个对象中,base不是未定义的(它是对象),所以它都很好并且不会抛出任何错误。这样解决了:

  

当V是具有基本基值的属性引用时,GetValue使用以下[[Get]]内部方法。使用base作为其值并使用属性P作为其参数调用它。采取以下步骤:

     

设O为ToObject(base)。

     

设desc是使用属性名P调用O的[[GetProperty]]内部方法的结果。

     

如果未定义desc,请返回 undefined

这就是你看到的原因:

window.a; // undefined

功能参数

另一种情况 - 参数完全不同,参数存在,但其值设置为原始值类型undefined。现有的和未定义的并且不存在之间存在差异:)

这是specified here

  

如果n大于argCount,则让v为undefined,否则让v为args的第n个元素的值。

这就是原因:

(function(a) { return a; } )(); // returns undefined

答案 1 :(得分:1)

你真的过分思考你的第二个案例:(function(a) { return a; } )(); // returns undefined

是的,但它与此无关:

  

...向上移动范围链并在全局窗口范围结束,其中a不是窗口的属性,因此返回undefined

您为该函数定义了一个名为a的参数。因为您没有提供值,所以它是undefined。这真的很简单。