Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScripts with()语句中局部变量的行为_Javascript_Jquery - Fatal编程技术网

JavaScripts with()语句中局部变量的行为

JavaScripts with()语句中局部变量的行为,javascript,jquery,Javascript,Jquery,我注意到了一些奇怪的行为(据我所知,至少在ECMA 3.0规范中是未定义的行为),请看下面的代码片段: var foo = { bar: "1", baz: "2" }; alert(bar); with(foo) { alert(bar); alert(bar); } alert(bar); 它在Firefox和Chrome中都会崩溃,因为第一个警报()中不存在“bar”;声明,这是意料之中的。但是,如果在with()-语句中添加一个bar声明,则它如下所示: var foo

我注意到了一些奇怪的行为(据我所知,至少在ECMA 3.0规范中是未定义的行为),请看下面的代码片段:

var foo = { bar: "1", baz: "2" };
alert(bar);
with(foo) {
    alert(bar);
    alert(bar);
}
alert(bar);
它在Firefox和Chrome中都会崩溃,因为第一个警报()中不存在“bar”;声明,这是意料之中的。但是,如果在with()-语句中添加一个bar声明,则它如下所示:

var foo = { bar: "1", baz: "2" };
alert(bar);
with(foo) {
    alert(bar);
    var bar = "g2";
    alert(bar);
}
alert(bar);
它将产生以下结果:

未定义,1,g2,未定义

似乎您在with()语句中创建了一个变量,大多数浏览器(在Chrome或Firefox上测试)也会使该变量存在于该范围之外,它只是设置为undefined。现在,从我的透视图来看,条形图应该只存在于with()-语句中,如果您让示例更奇怪:

var foo = { bar: "1", baz: "2" };
var zoo;
alert(bar);
with(foo) {
    alert(bar);
    var bar = "g2";
    zoo = function() {
        return bar;
    }
    alert(bar);
}
alert(bar);
alert(zoo());
它将产生以下结果:

未定义,1,g2,未定义,g2

因此with()-语句中的
bar
并不存在于其外部,但运行时以某种方式“自动”创建了一个名为bar的变量,该变量在其顶级范围(全局或函数)中未定义,但该变量与with()-语句中的变量不同,并且该变量仅在with()语句中存在-语句中定义了一个名为bar的变量


非常奇怪,而且前后矛盾。有人对这种行为有什么解释吗?ECMA规范中没有这方面的内容。

这是ECMA-262第三版第12.2节中的内容,如下所示

变量是在输入执行范围时创建的。块不定义新的执行范围

带有初始值设定项的变量在执行VariableStatement时,而不是在创建变量时,分配其AssignmentExpression的值

这意味着您必须将带有初始值设定项的声明视为两个独立的步骤:首先,在进入函数(执行脚本)时,在函数局部(全局)范围内创建一个新变量,但在到达语句之前,您不会赋值。在您的示例中,此时由于
with()
,作用域链已更改,赋值将看到重载变量,而新创建的变量未定义

这意味着

with({ foo : 42 }) {
    var foo = 'bar';
}
被解析为

with({ foo : 42 }) {
    var foo;
    foo = 'bar';
}
这相当于

var foo;
({ foo : 42 }).foo = 'bar';

因此,未初始化
foo

这是ECMA-262,第3版,§12.2中的如下内容:

变量是在输入执行范围时创建的。块不定义新的执行范围

带有初始值设定项的变量在执行VariableStatement时,而不是在创建变量时,分配其AssignmentExpression的值

这意味着您必须将带有初始值设定项的声明视为两个独立的步骤:首先,在进入函数(执行脚本)时,在函数局部(全局)范围内创建一个新变量,但在到达语句之前,您不会赋值。在您的示例中,此时由于
with()
,作用域链已更改,赋值将看到重载变量,而新创建的变量未定义

这意味着

with({ foo : 42 }) {
    var foo = 'bar';
}
被解析为

with({ foo : 42 }) {
    var foo;
    foo = 'bar';
}
这相当于

var foo;
({ foo : 42 }).foo = 'bar';

因此没有初始化
foo

我想你只是对范围有点误解。我并不是在责怪你,如果你来自大多数其他语言,那你会说“WTF?”。Javascript有我称之为“FUBAR作用域”(我确信这里有一个合适的术语,但我从来没有费心去学习它……知道它是如何工作的>知道它叫什么,至少对我来说是这样)

:

with()
允许对变量进行块级定义,以便传递到作用域()。但是…它没有将变量限制在此范围内,它在之后可用:

如果
with()
是您正在处理的元素的闭包,那么
将引用我们传递到with()中的
{bar:1}
对象,但它不是:)<代码>此在本例中仍然是
窗口的全局上下文
。由于您仍在该上下文中执行,因此您定义的任何变量都将在该上下文中可用,因此在函数的
with()
后面可用,因为它们的定义范围比您想象的要高得多。直觉告诉您它是在一个更受约束的范围内定义的:在
with()
…但是javascript不同,它完全取决于闭包运行的上下文

我试图为这种行为找到一个好的描述,它提供了更多的范围示例。总的来说,这更像是一个闭包/范围问题,而不是
with()
明确地说,这个网站更详细地介绍了整个概念,以防我解释得很糟糕……我知道这在很多方面都是一个落后的概念,对不起


我想你只是对范围有点误解。我并不是在责怪你,如果你来自大多数其他语言,那你会说“WTF?”。Javascript有我称之为“FUBAR作用域”(我确信这里有一个合适的术语,但我从来没有费心去学习它……知道它是如何工作的>知道它叫什么,至少对我来说是这样)

:

with()
允许对变量进行块级定义,以便传递到作用域()。但是…它没有将变量限制在此范围内,它在之后可用:

如果
with()
是您正在处理的元素的闭包,那么
将引用我们传递到with()中的
{bar:1}
对象,但它不是:)<代码>此在本例中仍然是
窗口的全局上下文
。由于您仍在该上下文中执行,因此您在其中定义的任何变量都将在该上下文中可用,因此在函数后面的
with()
之后可用,因为它们已定义