Javascript:z=z | |[]在不使用VAR时抛出错误-为什么?

Javascript:z=z | |[]在不使用VAR时抛出错误-为什么?,javascript,var,scoping,operator-precedence,hoisting,Javascript,Var,Scoping,Operator Precedence,Hoisting,出于对知识的好奇,为什么javascript会接受 var z = z || []; 初始化z(如z最初定义) 但是如果没有var,它会抛出一个错误(在全局空间中) (如果z之前未定义) 在全局空间中,您不需要使用VAR,尽管我知道这可能是一种不好的做法 在你说之前,这是一个重复的问题,如 注意声明“如果您在全局范围内,那么没有区别。” 很明显,以我的工作为例,这不是100%正确的 这是一个怪癖还是有合理的逻辑 添加我学到的答案摘要: 多亏了Tim(见下文),我误解的关键在于没有意识到这一

出于对知识的好奇,为什么javascript会接受

var z = z || [];
初始化z(如z最初定义)

但是如果没有var,它会抛出一个错误(在全局空间中)

(如果z之前未定义)

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

在你说之前,这是一个重复的问题,如

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

很明显,以我的工作为例,这不是100%正确的

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


添加我学到的答案摘要:

多亏了Tim(见下文),我误解的关键在于没有意识到这一点(javascript的基础)

var z;如果z已经存在,则绝对不执行任何操作

如果您错误地假设“var z”总是初始化,那么这个表达式似乎是双向的

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

这是一篇关于Javascript中此类范围界定和提升问题的优秀文章:


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

效果是正确的
var
始终会立即声明其“操作数”,而当您不声明它时,脚本会尝试使用未定义的变量并抛出错误

如果你在全局范围内,你可以分配给一个不存在的变量,它的效果和声明它的效果一样,这可能是一个糟糕的做法。当然,在你的情况下,它是未定义的。话虽如此,尽管这可能是出于智力上的好奇心,但你永远不会写作

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

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

。事实上,当我在全局范围内声明事物时(它从来都不是
;)
),我使用
窗口。取而代之的是一些
,因为它使我的意图更加清楚。

您可以将未声明的变量
z=123
;但是,您可能不会尝试阅读一个与
z=z | |【】
相同的内容。

z=z |【】
将在范围链中没有
z
的任何范围(全局或非全局)中抛出。这是因为表达式首先尝试检索右侧名为
z
的现有变量的值,如果不存在该变量,则会出现错误

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


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

作为一般规则:复制实际错误消息通常比只写“抛出错误”更有用。如果不声明它,您的脚本试图使用未定义的变量-等等,您是说z=z访问z,但var z=z不访问?第二个z仍然在全局范围内,如果它在函数外部,则第一个z也是。(困惑)@ckè:区别在于使用
var
会导致在执行任何语句之前创建
z
变量。啊,我想我明白了。所以“VARz”首先在左侧完成,就像指示“创建一个新的z”,但是它在右侧寻找一个“旧的z”。按照这个顺序,“z”在左侧刚刚初始化,因此右侧的“z”不是未定义的,尽管它是空的。没有var,右边的“z”不仅仅是空的,它是未定义的。嗯,好的-如果“VARZ”在左边将其定义为新的,那么这段代码如何保留现有的值呢?它似乎有两种方式,从左边初始化到右边,但也可以保留右边的值。@ck:是的,我想你已经知道了,尽管术语需要注意,因为
undefined
在JavaScript中是一个实际值,实际上是分配给变量的默认值(例如,
var x;
创建了一个名为
x
的变量,其初始值为
undefined
,这不同于从未声明过的不存在的
x
)@ck:关于保留现有值,
var z;
如果
z
已经存在,那么它绝对不会做任何事情,不管它的值是什么。var z;如果z已经存在,那么它绝对不会做任何事。这简单地解释了我对这个问题缺乏理解的原因,以及为什么我感到困惑。我总是假设var z;会清除现有变量,然后将其初始化为空、空或类似。现在我得到了100%的答案,事后看来,这似乎是一个愚蠢的问题!
var z = z || [];
if(!window.z) {
    window.z = [];
}