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第二次声明它应该是未定义的,但它保持以前的值。请说明此重新声明是否有任何特殊目的。

4

9 回答 9

21

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

JavaScript 中的变量语句会被提升,这意味着它们在解析时被评估,然后在运行时进行分配。

您在解析阶段结束时的代码,在执行之前看起来像这样:

var x;
x = 5;

document.write(x);
document.write("<br />");
document.write(x);
于 2009-12-08T01:38:39.057 回答
7

var单独不执行任务。它仅表明当您在发生的整个范围内使用变量名称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:即使var在执行的过程中从未到达该语句foo(),它仍然可以有效地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 ; ...<...; ...++)为“哦,这只是一个标准的迭代器”),你有一个微妙而烦人的调试问题。

于 2009-12-08T01:59:38.117 回答
1

所以当它第二次声明的 x 应该是未定义的

规范的哪一部分是这样说的?

“未定义的行为”并不意味着“变量将是undefined”。

于 2009-12-08T01:32:31.390 回答
0

就我对 javascript 的理解而言,关键字的使用在全局范围内var是完全可选的。对于函数来说,情况就不同了。

在函数内部时,使用var关键字来指示该变量是函数的局部变量(而不是默认全局变量)。

我个人var在全局范围内使用来表明第一次声明和/或使用变量。

您可以参考http://www.w3schools.com/js/js_variables.asp了解更多信息。

于 2009-12-08T01:32:02.670 回答
0

第二个 var x 完全是多余的。

于 2009-12-08T01:32:45.927 回答
0

同一范围内,完全没有必要“重新声明”一个变量。

于 2009-12-08T01:34:13.770 回答
0

此外,程序员可能希望使用var本地化变量:

<script>
var x= 'this is global x';
function my_x() {
 var x= 'localized x';
 alert(x);
}
my_x();
alert(x);
</script>
于 2009-12-08T01:38:45.710 回答
0

永远不应该在同一范围内重新声明一个变量,如果你真的想改变它然后分配给它。在这种动态语言中创建不同的对象不需要重新声明,如果您希望 x 是一个字符串,只需分配:

x = "hello";

不需要先将其设置回未定义或重新声明。

请注意,在大多数情况下更改变量类型并不是很好的做法,只需说明如果您需要的话,这是一种可能性。

于 2009-12-08T01:39:27.590 回答
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,因为这是一种新的用法。这意味着我可以重新排序代码,或者注释掉前半部分,而不会破坏任何东西。

于 2016-12-21T19:15:16.443 回答