重新声明JavaScript变量

53

这个教程中写道:

如果重新声明JavaScript变量,它不会失去它的值。

我为什么要重新声明一个变量?在某些情况下,它是否实用?

谢谢


12
http://w3fools.com/ - Quentin
8个回答

63

这只是一个提醒,如果你这样做:

var x=5;
var x;
alert(x);

结果将为5。

如果在其他一些语言中重新声明变量,例如,结果将为未定义(undefined)或NaN,但不适用于JavaScript。


有趣。当我尝试重新声明一个类时,我会得到相同的错误。我有一个Animal类,它有一个通用的speak函数,看起来像console.log(this.name + 'makes a sound.')。当然,在我声明它之后,我意识到“make”需要在引号和单词之间加上一个空格。所以我导航到该条目,进行了相应的修复,并重新提交,认为新的声明将覆盖先前的声明。显然,这不是javascript的工作方式。那么我该怎么处理呢? - Musixauce3000
2
如果使用let或const重新声明变量,则JavaScript会抛出错误。然而,使用var重新声明变量不会引发异常。后面的声明仅仅是覆盖了前面的声明。 - Murali Mohan
我认为指出以下内容也很有用:如果你执行 var x=5; var x=x+10; alert(x);,结果将是15,即在第二个 var 中,第一个 var 分配的 x 的原始值是可访问的,并且可以在 RHS 表达式中使用。 - Doin

47

Google Analytics中可以找到重新声明变量的示例。当Google Analytics脚本启动JavaScript跟踪代码时,它以如下方式声明或重新声明_gaq

var _gaq = _gaq || [];
换句话说,如果已经定义了_gaq变量,_gaq会被"重新声明"为其自身。如果未定义,则首次声明为空数组。
这使得Google Analytics跟踪代码能够支持其他可能需要在Google Analytics代码初始化之前使用变量的脚本。正如@xralf指出的那样,JavaScript允许这样做。
在无法确定变量是否已经定义的情况下,重新声明变量非常有用。
通过有条件地重新声明变量,就像Google Analytics跟踪代码所做的那样,允许变量安全地起源于多个位置。
在这个例子中,其他使用_gaq变量的代码也可以安全地检查预定义的_gaq变量。如果存在,它知道可以使用它。如果不存在,它知道应该在尝试使用它之前定义它。

1
非常好的答案,+1,特别是关于允许变量“安全地来自多个位置”的注释。当您将JS块重构为单独的文件并希望能够根据需要使用一些部分时,能够像在_gaq示例中所提到的那样做会很有帮助(虽然变量名很可怕,不是吗?)。 - Amos M. Carpenter

21

为什么我需要重新声明一个变量?

你不应该这样做,它会导致代码混乱。

在某些情况下这样做很实用吗?

不是的。


你的回答非常好,但我只能选择一个来接受。 - xralf
更像是无意中或不知情地重新声明一个变量。 - Adnan
2
如果我在一个函数中有两个不嵌套的循环,并且声明的变量var i = 0仅在它被声明的循环内使用,那么为什么我要花心思去为第二个循环发明另一个名称呢?所以这至少是一个例子,变量重新声明是实用的,我认为。 - Dmitry Koroliov
2
我的意思是,这种方式更方便。你可以几乎不用担心是否应该添加/删除变量声明,就可以轻松地操作(复制/粘贴等)代码行。 - Dmitry Koroliov
1
在同一个文件或函数内重新声明变量可能不是一个好的做法。但如果您有多个脚本文件(在HTML页面的上下文中),那么通常情况下您需要在2个或更多的文件中重新声明变量;请参考Steve Oliver的答案。因此,这不是一个好的答案。 - Doin
显示剩余4条评论

9
在 JavaScript 中不存在块级作用域,所以建议为澄清目的重新声明变量;这将使代码更加优秀。
例如:
for (var x=0; x< 100; x++) { }

alert(x); //In most languages, x would be out of scope here.
          //In javascript, x is still in scope.


//redeclaring a variable helps with clarification: 
var x = "hello";
alert(x);

2
现在有了 letconst - Manuel

5

它不会因为提升而失去其价值

var x = 5;
var x;

// this is same as

var x; // undefined;
x = 5;

当你说“如果重新声明JavaScript变量,它不会失去其值”时,

根据hoisting的规则,所有声明都会被提升到顶部。然后变量被赋值。

var x = 25;
var x; // redeclare first time
var x; // redeclare second time

// is same as 

var x; // undefined
var x; // Not sure if this happens, but doesn't make a difference, it's still undefined
x = 25;

就实用性而言,有时候会发生这种情况。看看 @steveoliver 的回答。


3

请记住,只有使用var声明的变量可以被重新声明。如果您尝试重新声明使用letconst声明的变量(这是现今大多数情况下应该使用的 ES2015 JavaScript 语法),情况会更糟糕,除了失去该值之外,还会抛出一个错误

let foo = 'foo';
let foo;

因此,在使用现代Javascript语法的代码库中,重新声明变量是不可能的 - 解释器需要能够识别代码中letconst变量得到正确初始化的单一点。在此之前,变量名将存在于暂时性死区中。

1
一般来说,由于提升(请参见此处)的问题,将var赋值语句放在其他语句之后被认为是不好的风格。使用“单变量模式”(请参见此处),重新声明只能像Steve Oliver的Google Analytics示例中那样发生。我会重构上面的示例为:
var x, max = 100; // no further var declarations afterwards!

for (x = 0; x < max; x++) { }

alert(x);

// redeclaration 'var x = "hello"' doesn't make any sense here
// and would be complained about by JSLint/-Hint 
x = 'hello';
alert(x);

重新声明可能是有意义的,特别是在使用可选参数的默认值时(我想这就是Google Analytics示例的用途):

function abc(param1) {
  var param1 = param1 || 'default value';
}

-1

重新声明变量其实很简单,它并不会对任何东西产生影响,你只需要记住,如果在作用域内重新分配值,则重新分配的值仅限于该作用域内,在作用域外部仍然是全局声明的值。

var page =1 ;
function htmlcode(page) { 
page = "keka";
console.log("inside " + page);
}

htmlcode(page);
console.log("inside " + page);

Output : inside keka
         inside 1

1
你错了。在你的情况下,它没有改变全局变量“page”的原因很简单,那就是你创建了一个带有相同名称参数的函数。 - peq42

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