如果我多次声明同一个变量,会有什么问题吗?

5

假设我有一些代码:

//Javascript
var elements = [];
function addNumbah1(){
    var i = 1;
    elements.push(i);
}
function addNumbah2(){
    var i = 2;
    elements.push(i);
}

一直持续到addNumbah999(),每次声明i变量是否不好?那会有什么问题吗?应该这么做:

//Javascript
var elements = [];
var i
function addNumbah1(){
    i = 1;
    elements.push(i);
}
function addNumbah2(){
    i = 2;
    elements.push(i);
}

1
你的两个语法不等价。你需要一个还是三个变量? - Álvaro González
1
在函数中声明变量会使它们成为该函数的局部变量 - 在您的第二个示例中,您正在声明全局作用域的变量。 - kinakuta
你的第一个函数在每个函数中声明了一个局部变量 i。每次调用 addNumbah1()i 的值都将是 1。第二个函数则声明了一个全局变量 i,并在每次调用时重置为新的值,但在每个函数中都使用了全局变量。 - Michael Berkowski
@ÁlvaroG.Vicario,您能澄清一下您的意思吗? - ChapmIndustries
@ChapmIndustries:这取决于您的用例。有时您希望在更高的范围内更改变量,以便其他人注意到它,而其他时候则必须避免这样做,以免破坏某些东西。告诉我们您的代码应该做什么(解决什么问题),我们可以告诉您变量是应该全局还是局部的。 - Bergi
显示剩余3条评论
6个回答

22

简短回答:,JS将所有变量声明提升到作用域顶部,无论您声明了多少次:

var i = 0
for (var i=0;i<10;i++)
{
    var j = i%2;//declared 10 times, on each iteration
}

将被翻译为

var i, j; //i is undefined at this point in the code.
for (i = 0;i<10;i++)
{
    j = i%2;//declared 10 times, on each iteration
}

在你的第一个示例中,你将i声明为函数作用域中的变量,这是你必须做的,以避免使全局范围混乱。这些变量使用的内存在函数调用时分配,在函数返回时释放(粗略地说,闭包是一个例外,但那会让我们偏离主题)。考虑以下代码:

var i = 10;
function someF()
{
    var i = 1;
    alert(i);
}
someF();//alerts 1 <-- value of i, local to someF
alert(i);//10, global i is unchanged

但如果你省略了 var

function someF()
{
    i = 1;
    alert(i);
}

你会看到数字1被警告了两次。如果JS在当前作用域中找不到变量声明,它将查找更高的作用域,直到找到一个var。 如果没有找到变量,JS将在最高作用域(全局)为您创建一个。 有关隐含全局变量的更详细示例,请在此处检查我的答案,或者阅读MDN页面,特别是关于名称冲突的部分。

最后,我想补充一点,全局变量,特别是隐含全局变量,是有害的。并且要知道,ECMA6标准明显远离全局变量,并引入对真正块级作用域的支持。您可以在这里看到。 哦,如果你想检查一个函数是否使用隐含全局变量:'use strict';是一个很好的东西:

(function()
{
    'use strict';
    var localVar = 123;//ok
    impliedGlobal = 123;//TypeError!
}());

如您所见,隐式全局变量是不允许的。请参考MDN关于严格模式的完整解释


非常好的并且详细的回答。它确实值得我投票。 - Naeem Ul Wahhab
谢谢!第一个完整且彻底回答问题并解释原因的人。 - ChapmIndustries

0

你之前的方法是可以的。每个 i 的实例都不会知道其他函数中的 i。

你应该阅读一下这篇关于全局变量与局部变量的教程。

另外,我能否建议一个优化。为什么不能只做以下操作来涵盖任何数字(而不是为每个数字单独创建函数)?

var elements = [];
function addNumbah(number){
    elements.push(number);
}

0

你可以多次声明一个变量。在你的代码中,你在不同的作用域中声明了变量 i:

   //Here you are declaring variable i local to addNumbah1,2 functions 
   var elements = [];
   function addNumbah1(){
       var i = 1; 
       elements.push(i);
   }
   function addNumbah2(){
       var i = 2; 
       elements.push(i);
   } 


   //Here v /variable i has been declared globally
   var elements = [];
   var i
   function addNumbah1(){
       i = 1;   
       elements.push(i);
   }
   function addNumbah2(){
       i = 2;  
       elements.push(i);
   }

请注意,虽然您可以多次声明变量,但通常这不是一个好的编程实践,因为它可能会在应用程序中引起错误/问题。

你没有重新声明任何变量,而是使用了隐含的全局变量!不要这样做。 - Elias Van Ootegem
@EliasVanOotegem 朋友,我并不是在自夸。我只是试图通过粘贴他的代码并在注释中描述全局和局部作用域来帮助发布这个问题的人。 - Naeem Ul Wahhab
当我评论时,第一个片段还不存在 - 只有一个全局示例和变量每次重置的解释(这根本不是真的:只有声明被提升。表达式无法被提升,这就是为什么IIFE需要()位:将函数转换为表达式) - Elias Van Ootegem
很抱歉这么龟毛,但今天我刚好在研究这个问题,因为它引起了我的注意。无论如何:愉快的编程。再次抱歉这么龟毛。 - Elias Van Ootegem
@EliasVanOotegem 我称呼你为朋友 :-) 所以不要抱歉。我知道你比我更懂。你刚刚帮助我进步了 :-) - Naeem Ul Wahhab

0

函数内声明的变量仅存在于该函数的范围内,因此在不同函数中具有相同变量名不会造成任何错误。

事实上,将变量保持在尽可能小的范围内是一个好习惯!全局变量可能很难管理,并且可能会创建非常糟糕的错误,特别是当另一个函数尝试访问变量时,其中一个函数没有使用该变量。

特别针对简单变量,声明:

var i = 0;

每次都很完美。


0
第二种形式,使用全局变量 i 实际上可能会慢一些,因为它在更高的作用域中定义,并且在更高的作用域中定义的变量需要更长的时间来解析。
除了任何性能方面的考虑外,只要遵循常规指导方针,除非性能真正是一个问题。在这种情况下:请尽可能地将您的变量范围缩小。
我强烈建议您使用第一种形式。

0

在不同的函数中声明相同名称的变量是可以的。


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