【发布时间】:2009-12-19 13:26:33
【问题描述】:
var 关键字遇到了一个非常奇怪的(对我而言)问题。我已将其缩减为一个相当小的测试用例,并发现它在 Node.js(因此是 V8 和 Chrome)、Safari 4 的检查器(因此是 Nitro)和 FireBug(显然是 SpiderMonkey)中都有体现。我最初是在准备一份错误报告,但由于它被广泛展示,我将假设我完全误解了 JavaScript 应该如何界定和查找变量。
测试用例非常小,在 GitHub 上:http://gist.github.com/260067。第一个示例和第二个示例之间的唯一区别是包含了 var 关键字。
这里还有一个类似的测试用例,它以不同的方式展示了相同的“问题”:https://gist.github.com/698b977ee0de2f0ee54a
编辑:为了排除任何试图解释级联作用域如何工作的答案,我对此非常熟悉。我的问题是我不明白为什么下面的代码“有效”(因为它alert()s 是“外部”,然后是“内部”,然后是“外部”):
(function(){
var foo = 'outer';
alert("Outer `foo`: " + foo);
(function(){
foo = 'inner';
alert("Inner `foo`: " + foo);
var foo;
})();
alert("Outer `foo`: " + foo);
})();
var foo; 出现在与foo 重新分配完全无关的位置;那么为什么它会以非常重要的方式影响该分配呢?
【问题讨论】:
-
你为什么使用评估?绝对没有理由在您发布的代码中使用 eval。
-
演示问题。实际的实现有很大的不同;你可以在这里看到它:github.com/elliottcable/poopy.js/blob/new-acquire/lib/…
-
您的最后一个示例有效,因为 1) foo = 'inner';将值分配给此函数有权访问的父范围 foo。 2) 你不需要使用 var 来声明一个变量。
-
看,错了。这就是我认为会起作用的方式,但事实并非如此。运行该代码(我刚刚在 V8 和 Nitro/WebKit 中对其进行了测试),最后一个警报仍将是“外部”。也就是说,
foo = 'inner';被限定在子范围内,因为末尾的var foo;的功能。 -
好的,我现在明白了。我同意这令人困惑,但这就是为什么使用 JavaScript 的技巧之一是在函数的开头声明所有变量。它可以阻止您今天遇到的错误发生。
标签: javascript v8 spidermonkey