循环内的Javascript变量声明

dgo*_*dgo 6 javascript variables performance loops

我有一种习惯,即我处于边缘强迫状态,但我认为可能完全没有必要.使用以下代码:

function abc(){
  var a,b;
  for(var i=0;i<10;i++){
    a=document.getElementsByTagName('LI').item(i).width;
    b=document.getElementsByTagName('DIV').item(i).width;
    // now do something with a and b
   }
   return;
}
Run Code Online (Sandbox Code Playgroud)

我强迫在循环之前声明变量而不是:

function abc(){
  for(var i=0;i<10;i++){
   var a=document.getElementsByTagName('LI').item(i).width;
   var b=document.getElementsByTagName('DIV').item(i).width;
    // now do something with a and b
   }
   return;
}
Run Code Online (Sandbox Code Playgroud)

请注意,在第二个代码块中,我var每次循环迭代时都定义变量.我想第一个是可读性等的最佳实践.但有时候我只是在攻击某些东西而不需要遵循最佳实践.

我的问题是:

是否有任何理由定义将使用var循环内的关键字重新定义的变量?

jfr*_*d00 13

由于Javascript中的变量提升var,在函数顶部或for循环内部之间的执行没有技术差异.如果这就是你所关心的,那么你可以这样做.

只是为了刷新内存,Javascript提升意味着解析像你的第二个代码块一样的代码,然后就像你的第一个代码块一样执行.var函数中的所有声明在执行之前自动移动到函数作用域的顶部.这些变量的赋值保存在代码中的位置 - 只需移动变量的声明.

所以,差异更多的是你想要编码的样子.当您将var定义放在for循环中时,它会使代码看起来像是为循环的每次迭代重新创建变量for,即使情况并非如此.它们在循环的每次迭代中被赋值,但是不创建新变量.如果您使用let而不是var因为let具有块范围而var仅具有函数范围,则会出现这种情况.

通常,将代码放在实际需要在循环内的循环中是一个好习惯.虽然它实际上并没有改变执行中的任何内容,无论var是在循环内部还是外部,但它只是一个良好实践的一部分,而其他代码在循环内部或外部可能会产生影响.

在你的情况下,我认为这将是一个更好的做法:

function abc(){
  var liTags = document.getElementsByTagName('LI');
  var divTags = document.getElementsByTagName('DIV');
  var len = Math.min(liTags.length, divTags.length);
  var a,b;

  for(var i = 0; i < len; i++){
    a = liTags[i].width;
    b = divTags[i].width;

    // now do something with a and b

   }

   return;
}
Run Code Online (Sandbox Code Playgroud)

在这里,您已经document.getElementsByTagName()从循环中删除了两个调用,这将产生巨大的性能差异.


2017年更新 .Javascript版本ES6,现在支持constlet声明变量.它们是块作用域,而不是函数作用域var,所以如果你在for循环块中声明其中一个,那么将为每次for循环调用创建一个新的独立变量.虽然这不会对您显示的代码类型产生任何重大的执行差异,但如果您在循环内部引用了您声明的变量的异步代码,则可能会有所不同.在循环体内constlet在循环体内使用的情况下,每个异步调用都会获得它自己的变量的单独副本,这有时非常方便.

  for(var i = 0; i < len; i++){
      let a = liTags[i].width;
      let b = divTags[i].width;

      $.get(someUrl).then(function(data) {
          // each call to $.get() here in the loop has it's own a and b
          // variables to use here, which would not be the case with var
      });

   }
Run Code Online (Sandbox Code Playgroud)

  • @ user1167442 - `getElementsByTagName()`返回***live HTMLCollection***.这意味着它找到的所有元素最初都存在,但如果DOM在您使用数据结构时发生更改,则结果将实时更新.这可能是一种祝福和诅咒(在我看来更常见的是诅咒),如果你在以一种会影响HTMLCollection本身的方式改变DOM的同时处理HTMLCollection,你必须注意这一点.实际上,将HTMLCollection复制到静态数组中是有意义的,以防止它发生变化. (3认同)