Do循环检查数组.每次将I与array.length进行比较时

Do loops check the array.length every time when comparing i against array.length?

本文关键字:length array 比较 检查 循环 数组 Do      更新时间:2023-09-26

我正在浏览,我发现了这个:

var i, len;
for(i = 0, len = array.length; i < len; i++) {  
   //...
}

我的第一个想法是:

    他为什么那么做?(出于某种原因,它肯定更好)
  • 值得吗?(我想是的,否则他为什么会这样做?)

正常循环(不缓存长度的)每次检查array.length吗?

按如下方式执行一个由三部分组成的循环:

for (A; B; C)
A - Executed before the enumeration
B - condition to test
C - expression after each enumeration (so, not if B evaluated to false)

所以,是的:如果数组被构造为for(var i=0; i<array.length; i++),则在每次枚举时检查其.length属性。对于微优化,将数组的长度存储在临时变量中是有效的(参见:在JavaScript中循环遍历数组的最快方法是什么?)。

等价于for (var i=0; i<array.length; i++) { ... }:

var i = 0;
while (i < array.length) {
    ...
    i++;
}
值得吗?(显然是的,不然他为什么要这样做呢?)

绝对是的。因为,正如你所说,循环每次都会计算数组长度。这将造成巨大的开销。在您的firebug或chrome开发工具vs.

中运行以下代码片段<>之前//创建一个包含50,000个条目的数组(函数(){窗口。Items = [];For (var I = 0;我& lt;50000;我+ +){items.push(我);}}) ();//一个以毫秒为单位返回给定函数执行时间的分析器函数var getExecutionTime = function(fn) {var start = new Date().getTime();fn ();var end = new Date().getTime();Console.log (end - start);}Var优化=函数(){var newItems = [];For (var I = 0, len = items.length;我& lt;兰;我+ +){newItems.push(项目[我]);}};var unOptimized = function() {var newItems= [];For (var I = 0;我& lt;items.length;我+ +){newItems.push(项目[我]);}};getExecutionTime(优化);getExecutionTime(硬度);之前

以下是在不同浏览器下的大致结果

<>之前浏览器优化未优化Firefox 14 26Chrome 15 32Ie9 22 40Ie8 82 157Ie7 76 148之前

所以再考虑一下,并使用优化的方式:)
注意:我试图在jsPerf上工作这段代码,但我现在无法访问jsPerf。我想,当我尝试的时候,它下降了。

我一直认为在JavaScript中长度只是数组对象的一个属性,由先前的数组操作(创建、添加、删除)预先计算出来,或者由用户重写,所以您只是在查找一个变量?我必须承认,我只是假设,因为缺乏括号,但查看MDN页面的数组。长度,似乎在说同样的事情。

在语言中,长度是一个方法或长度是由标准库函数计算的,那么你应该在运行循环之前预先计算长度,这样数组就不会每次迭代都计算,特别是对于大型数据集。即便如此,在Python等现代高级语言中,len()仍然只返回数组对象的length属性。

所以,除非我弄错了,复杂度只是O(1),从这个角度来看,即使变量在每次传递时比属性查找快一点,也不值得在for循环保护作用域之外创建/重用额外的变量。

然而,我怀疑在这种情况下,示例的程序员选择这种方法的原因仅仅是他们在另一种语言中养成的习惯,并将JavaScript发扬光大。

这样做的一个原因是,如果您在循环期间向数组添加元素,但不希望遍历它们。假设你想把[1,2,3]变成[1,2,3,1,2,3]。你可以输入:

var initialLength = items.length;
for(var i=0; i<initialLength; ++i) {
    items.push(items[i]);
}

如果在循环前不保存长度,则数组。长度将继续增加,循环将一直运行,直到浏览器崩溃/终止它。

除此之外,正如其他人所说,它会轻微影响性能。我不会养成这样做的习惯,因为"过早优化是万恶之源"。另外,如果在循环期间更改数组的大小,这样做可能会破坏代码。例如,如果在循环期间从数组中删除元素,但继续将i与先前的数组大小进行比较,则循环将尝试访问超出新大小的元素。

是它检查数组。但是如果我们不想运行递增数组的循环,那么在这种情况下,我们可以使用forEach方法。

forEach是一个javascript中的构建方法,它类似于for循环,但forEach只迭代数组中循环开始前的元素。

让我们从下面的代码片段中理解:

array = [1,2,3,4]
for(i=0;i<=array.length;i++){
console.log(array[i]);
array.push(array[i]+1);
}

输出123.456...当它在检查数组时,继续(infinite)每次长度

让我们检查一下forEach方法

array = [1,2,3,4]
array.forEach((element) => {
console.log(element);
array.push(element+1);
})
console.log("array elements after loop",array);

只处理数组中在迭代开始前存在的4个元素。

**但是在forEach的情况下,它会影响数组。如果从数组中弹出元素,则为长度

让我们看一个例子:

array = [1,2,3,4]
array.forEach((element) => {
console.log(element);
array.pop()
})
console.log("array elements after loop",array);

下面是针对不同方法的一些性能测试

http://www.websiteoptimization.com/speed/10/