【问题标题】:Javascript: z = z || [] throws an error when not using VAR - why?Javascript:z = z || [] 在不使用 VAR 时抛出错误 - 为什么?
【发布时间】:2012-01-30 16:00:56
【问题描述】:

出于求知欲,javascript为什么接受

var z = z || [];

初始化z(如z最初定义的那样)

但没有 var,它会抛出错误(在全局空间中)

z = z || [];

(如果 z 之前未定义)

在全局空间中,您不需要使用 VAR,尽管我知道这可能是不好的做法。

在您说之前,这是重复的问题,例如

What is the purpose of the var keyword and when to use it (or omit it)?

请注意声明“如果您在全局范围内,则没有区别。”

鉴于我的工作示例,这显然不是 100% 正确的。

这是一个怪癖还是有合理的逻辑?


添加我所学的答案摘要:

感谢 Tim(见下文),我误解的关键是没有意识到这一点(javascript 基础)

变量 z;如果 z 已经存在,则什么都不做

如果你错误地假设“var z”总是初始化,这就是这个表达式似乎有两种方式的方式。

从左边开始,“var z”只是确保 z 已定义,但实际上不会影响任何现有值(如果它已经存在)。然后在右边,如果z已经存在,则使用它,如果不存在,则该变量刚刚声明(但为空),因此不会使用但不会抛出错误。

这是一篇关于 Javascript 中这种范围界定和提升问题的优秀文章: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

非常感谢 minitech 和其他所有做出贡献的人!

【问题讨论】:

  • 作为一般规则:复制实际的错误消息通常比写“抛出错误”更有帮助。

标签: javascript var scoping operator-precedence hoisting


【解决方案1】:

效果是对的。 var 总是会立即声明其“操作数”,而当您不声明它时,您的脚本会尝试使用未定义的变量并引发错误。

如果您在全局范围内,您可以分配给一个不存在的变量,它的效果与声明它的效果相同,这可能是一种不好的做法。当然,在您的情况下,它是未定义的。话虽这么说,尽管可能出于求知欲,但您永远不会写

var z = z || [];

因为这样做毫无意义。相反,您可以这样做:

if(!window.z) {
    window.z = [];
}

。事实上,当我在全局范围内声明事物时(绝不是 ;)),我会改用 window.<i>something</i>,因为它让我的意图更加清晰。

【讨论】:

  • 当您不声明它时,您的脚本会尝试使用未定义的变量 - 等等,您是说 z=z 访问 z 但 var z=z 没有?第二个 z 仍然在全局范围内,如果它在函数之外,第一个 z 也是如此。 (不解)
  • @ck_:区别在于使用var会导致在执行任何语句之前创建z变量。
【解决方案2】:

z = z || [] 将抛出范围链中没有 z 的任何范围(全局或非全局)。原因是表达式首先尝试检索右侧名为 z 的现有变量的值,当不存在时这是一个错误。

var z = z || [] 不抛出错误的原因是变量z 在表达式执行之前被创建(如果它不存在的话),这种效果通常被称为提升 .

另一方面,将值分配给未解析的标识符(例如z = 2)在任何范围内都不会出错(ECMAScript 5 严格模式除外,该模式禁止并抛出异常)。如果无法解析标识符,则将其添加为作用域链中最终对象的属性,即全局对象,因此看起来像是创建了一个全局变量。

【讨论】:

  • 啊,我想我明白了。所以“var z”首先在左侧完成,就像指示“create a new z”一样,然后它在右侧寻找“old z”。按照这个顺序,左边的“z”刚刚被初始化,所以右边的“z”不是未定义的,尽管它是空的。如果没有 var,右侧的“z”不仅是空的,而且是未定义的。嗯,好吧 - 如果“var z”在左边将它定义为新的,那么这段代码如何保留现有值呢?好像有两种方式,左边初始化为右边,也可以保持右边的值。
  • @ck_: 是的,我想你已经明白了,尽管术语需要注意,因为undefined 是 JavaScript 中的实际值,实际上是分配给变量的默认值(对于例如,var x; 创建了一个名为x 的变量,其初始值为undefined,这与从未声明过的不存在的x 不同)。我会选择“未声明”或“不存在”。
  • @ck_:关于保留现有值,如果z 已经存在,var z; 绝对不会做任何事情,无论其值如何。
  • var z;如果 z 已经存在,则绝对不执行任何操作 - 简而言之,这解释了我对这个问题缺乏理解以及为什么我感到困惑。我一直认为 var z; 会清除现有变量并将其初始化为空或 null 或类似的。现在我得到了 100%,事后看来这似乎是一个愚蠢的问题!
【解决方案3】:

您可以分配给未声明的变量z = 123;但是,您可能不会尝试阅读 z = z || [] 所做的内容。

【讨论】:

    猜你喜欢
    • 2023-01-19
    • 2023-03-19
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2020-11-14
    相关资源
    最近更新 更多