JavaScript变量重新声明有什么意义吗?

6

我是JavaScript的新手。

<html>
<body>
<script type="text/javascript">
var x=5;
document.write(x);
document.write("<br />");
var x;
document.write(x);
</script>
</body>
</html>

结果是:

5
5

当第二次声明x时,它应该是未定义的,但它仍然保留之前的值。请说明这种重新声明是否有特殊目的。


您的问题内容涉及一个具体的示例,已经在下面得到了很好的回答。然而,我发现类似问题的这个答案非常好地回答了您的问题标题中所问的通用情况(何时/为什么会重新声明 JavaScript 变量?)。 - Amos M. Carpenter
9个回答

21

你并没有真正地重新声明变量。

在JavaScript中,变量声明会受到提升的影响,这意味着它们会在解析时进行评估,然后在运行时进行赋值操作。

在解析阶段结束之前,你的代码大致如下:

var x;
x = 5;

document.write(x);
document.write("<br />");
document.write(x);

7

var关键字本身并不执行赋值操作。它只是标志着在该作用域内使用变量名时,你正在讨论一个局部变量而不是全局变量(这是有争议的默认值)。var关键字会在函数解析时被识别,并在整个作用域中有效,所以它出现的位置是无关紧要的:

var a= 0;

function foo() {
    a= 1;
    return a;
    var a;
}

var b= foo();
alert('global a='+a+', local a='+b);

global a=0, local a=1 中的结果是:尽管在执行 foo() 的过程中从未到达 var 语句,但它仍然有效地使 a 成为局部变量。

因此,在同一作用域内第二次声明 var x 是完全多余的。但有时您可能仍会这样做,通常是在同一函数内将局部变量名称用于第二个独立用途时。最常见的情况是:

for (var i= 0; i<onething.length; i++) {
    ...do some trivial loop...
}

for (var i= 0; i<anotherthing.length; i++) {
    ...do another trivial loop...
}

尽管你可以省略第二个var,像jslint这样的工具会要求你这样做,但实际上这可能不是一个好主意。 设想你稍后更改或删除第一个循环,使它不再声明ivar。现在,剩余的第二个循环突然从局部变量变成全局变量。如果你在更新第一个循环时没有注意到第二个循环对它有一个隐藏的依赖性(鉴于眼睛忽略了模式for(...=0 ; ...<...; ...++),你很可能没有注意到这一点),那么你就会遇到一个微妙而令人烦恼的问题,需要进行调试。

1
就我对Javascript的了解而言,在全局范围内使用var关键字是完全可选的。但对于函数来说则是另一回事。
在函数内部时,使用var关键字来表示该变量仅限于该函数内部(而不是默认为全局变量)。
个人而言,我会在全局范围内使用var来显示一个变量是否第一次被声明和/或使用。
您可以参考http://www.w3schools.com/js/js_variables.asp以获取更多信息。

2
不是这样的:如果没有指定“var”,变量会落入全局范围。 - jldupont
var 用于函数内的作用域,在函数内如果不使用 var,则自动成为全局变量。 - John Boker
嘿-都在同样的20秒内完成。 - John Boker
@Kenaniah: 你应该删除你的回答,否则你很快就会被大量的踩票所困扰... - jldupont
非常抱歉。我忘了提到它在函数中的用法,用于表示局部变量(与全局变量相对)。尽管问题涉及全局范围,但我应该包含这一点。帖子已编辑;-) - Kenaniah

1
所以当第二次声明时,x 应该是未定义的。
规范的哪个部分说明了这一点?
“未定义行为”并不意味着“变量将是未定义的”。

0
此外,程序员可能希望使用var来本地化一个变量:
<script>
var x= 'this is global x';
function my_x() {
 var x= 'localized x';
 alert(x);
}
my_x();
alert(x);
</script>

虽然这是可能的,而且非常好描述,但我不确定这是一个很好的实践方式,变量名通常不应该重复使用。 - Jay

0

那个第二个变量x是完全多余的。


0
在同一作用域内,“重新声明”变量是完全不必要的。

0

在同一作用域内,您绝对不应该重新声明一个变量。如果您真的想要更改它,那么请给它赋值。在这种动态语言中,不需要重新声明就可以创建一个不同的对象。如果您想让 x 成为一个字符串,只需赋值即可:

x = "hello";

你不需要将它设置回未定义或者重新声明。

请注意,在大多数情况下,改变变量类型并不是一个很好的实践方式,仅仅是在必要时提供这个可能性。


0

我最近写了这样的代码:

var obj1 = get_an_object();
var v = obj1.get_velocity();
v += changes_in_velocity();
obj1.set_velocity(v);

var obj2 = get_an_object();
var v = obj2.get_velocity();
v += changes_in_velocity();
obj2.set_velocity(v);

就浏览器而言,第二个var v语句是多余和无意义的。但对我来说,它有两个目的。首先,它告诉我忘记了我所知道的旧的v,因为这是一个新的用法。其次,它意味着我可以重新排列代码或注释掉前半部分而不会破坏程序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接