在 JavaScript 中遍历数组

Loop through an array in JavaScript

提问人:Mark Szymanski 提问时间:6/10/2010 最后编辑:Mateen UlhaqMark Szymanski 更新时间:11/13/2023 访问量:5330513

问:

在 Java 中,您可以使用循环遍历数组中的对象,如下所示:for

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray) {
    // Do something
}

我可以在 JavaScript 中做同样的事情吗?

JavaScript 数组循环 for 循环

评论

7赞 Mark Szymanski 6/10/2010
好的,所以我有点困惑,在访问对象时可以使用增强的 for 循环吗?并使用顺序填充一个?这是正确的吗?
54赞 Christian C. Salvadó 6/10/2010
不,这真的很简单,数组对象有数字索引,所以你想按数字顺序遍历这些索引,顺序循环确保,增强循环枚举对象属性,没有特定的顺序,它还举继承的属性......对于数组的迭代,始终建议使用顺序循环...for-in
7赞 jondavidjohn 11/2/2011
相关新闻 - stackoverflow.com/questions/5349425/...
9赞 EscapeNetscape 11/4/2016
jsben.ch/#/Q9oD5 <= 这里是一堆循环数组解决方案的基准测试
13赞 jpmc26 10/5/2018
@CMS 不,这并不简单。这在所有其他语言中都非常简单。这在 JS 中非常复杂,在那里你既可以使用它,也可以做不同的事情。然后你还有丑陋和烦人的基于索引的循环。所有其他现代语言都使循环访问集合变得简单明了,没有意外或混乱。JS 也可以,但事实并非如此。inofforEach

答:

5155赞 Christian C. Salvadó 6/10/2010 #1

三个主要选项:

  1. for (var i = 0; i < xs.length; i++) { console.log(xs[i]); }
  2. xs.forEach((x, i) => console.log(x));
  3. for (const x of xs) { console.log(x); }

详细示例如下。


1.顺序循环:for

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    console.log(myStringArray[i]);
    //Do something
}

优点

  • 适用于各种环境
  • 可以使用 和 流控制语句breakcontinue

缺点

  • 太啰嗦了
  • 祈使的
  • 容易出现偏离一的错误(有时也称为围栏柱错误)

2. :Array.prototype.forEach

ES5 规范引入了许多有益的数组方法。其中之一,Array.prototype.forEach,为我们提供了一种简洁的方法来遍历数组:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

ES5 规范发布(2009 年 12 月)已经快十年了,桌面、服务器和移动环境中几乎所有的现代引擎都实现了它,因此使用它们是安全的。

使用 ES6 箭头函数语法,它更加简洁:

array.forEach(item => console.log(item));

箭头功能也被广泛实现,除非您计划支持古老的平台(例如,Internet Explorer 11);你也可以安全离开。

优点

  • 非常简短和简洁。
  • 声明

缺点

  • 无法使用break / continue

通常,您可以通过在迭代数组元素之前过滤数组元素来替换命令性循环的需要,例如:break

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

请记住,如果要迭代一个数组以从中构建另一个数组,则应使用 .我已经见过很多次这种反模式了。map

反模式:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

地图的正确用例:

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

此外,如果您尝试将数组减少到一个值,例如,您想要对数字数组求和,则应使用 reduce 方法。

反模式:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

减少的正确使用:

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. ES6 语句:for-of

ES6 标准引入了可迭代对象的概念,并定义了用于遍历数据的新构造,即语句。for...of

此语句适用于任何类型的可迭代对象,也适用于生成器(具有 \[Symbol.iterator\] 属性的任何对象)。

根据定义,数组对象是 ES6 中内置的可迭代对象,因此您可以对它们使用以下语句:

let colors = ['red', 'green', 'blue'];
for (const color of colors){
    console.log(color);
}

优点

  • 它可以遍历各种各样的对象。
  • 可以使用正常的流控制语句 ( / )。breakcontinue
  • 可用于循环访问串行异步值。

缺点

请勿使用for...in

@zipcodeman建议使用该语句,但对于迭代数组应避免,该语句旨在枚举对象属性。for...infor-in

它不应用于类似数组的对象,因为:

  • 不保证迭代顺序;数组索引不能按数字顺序访问。
  • 还枚举了继承的属性。

第二点是,它可能会给你带来很多问题,例如,如果你扩展对象以包含一个方法,该属性也会被枚举。Array.prototype

例如:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
    console.log(array[i]);
}

上面的代码将控制台日志“a”、“b”、“c”和“foo!”。

如果您使用一些严重依赖原生原型增强的库(例如 MooTools),这可能是一个特别严重的问题。

正如我之前所说,该语句用于枚举对象属性,例如:for-in

var obj = {
    "a": 1,
    "b": 2,
    "c": 3
};

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
        // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

在上面的示例中,该方法仅允许枚举自己的属性。就是这样,只有对象物理上具有的属性,没有继承的属性。hasOwnProperty

我建议您阅读以下文章:

评论

13赞 bmaupin 6/15/2021
我知道这个答案早于 async 和 Promises,但我觉得在任何与现代 JavaScript 有关的对话中都值得一提:“ 不等待 promises。确保在使用 promises(或异步函数)作为回调时了解其含义。(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...forEachforEach)
7赞 Vic 9/9/2021
ES6的缺点:无法获取当前索引for-of
1赞 Alvaro Carvalho 2/17/2022
@Vic你可以,但这并不简单。
2赞 Scotty Jamison 5/15/2022
作为参考,这是在循环时获取当前索引的方法。我个人觉得这很简单。.for (const [i, x] of yourArray.entries()) { ... }
2赞 Scotty Jamison 5/15/2022
对于那些看到这个答案并想知道他们是否应该选择for-of的人,我只建议使用for-of。for-of 是较新的循环语法,它完全取代了对 forEach 的需求。for-of 提供的东西是 forEach 没有的,但反之则不然。
453赞 hasen 6/10/2010 #2

您可以使用 ,这是一种函数式编程技术,在 PythonHaskell 等其他语言中也可用。map

[1,2,3,4].map( function(item) {
     alert(item);
})

一般语法为:

array.map(func)

通常采用一个参数,该参数是数组的一个项目。但是在 JavaScript 的情况下,它可以采用第二个参数,即项目的索引,以及第三个参数,即数组本身。func

的返回值是另一个数组,因此您可以像这样使用它:array.map

var x = [1,2,3,4].map( function(item) {return item * 10;});

现在 x 是 .[10,20,30,40]

您不必以内联方式编写函数。它可以是一个单独的函数。

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

这相当于:

 for (item in my_list) {item_processor(item);}

除非你没有得到 .new_list

评论

103赞 harto 6/10/2010
该特定示例可能更好地使用 实现。 用于生成新数组。Array.forEachmap
21赞 Christian C. Salvadó 6/10/2010
@hasen,该方法是 ECMAScript 第 5 版标准的一部分,尚未在所有实现中都可用(例如 IE 缺少它),也用于迭代数组我认为 Array.prototype.forEach 方法在语义上更正确......另外,请不要建议 for-in 语句,请参阅我的回答以获取更多详细信息:)Array.prototype.map
94赞 kennebec 6/10/2010 #3

Opera、Safari、Firefox 和 Chrome 现在都共享一组增强的 Array 方法,用于优化许多常见循环。

您可能不需要所有这些,但它们可能非常有用,或者如果每个浏览器都支持它们,它们就会非常有用。

Mozilla Labs 发布了他们和 WebKit 都使用的算法,因此您可以自己添加它们。

filter 返回满足某些条件或测试的项的数组。

如果每个数组成员都通过测试,则 every 返回 true。

如果有任何通过测试,则返回 true。

forEach 在每个数组成员上运行一个函数,并且不返回任何内容。

map 类似于 forEach,但它返回每个元素的操作结果数组。

这些方法都采用一个函数作为其第一个参数,并具有可选的第二个参数,该参数是一个对象,当数组成员遍历该函数时,您希望将其作用域强加给数组成员。

忽略它,直到你需要它。

indexOflastIndexOf 查找与其参数完全匹配的第一个或最后一个元素的适当位置。

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();
132赞 sebarmeli 12/7/2010 #4

在 JavaScript 中,不建议使用 for-in 循环遍历 Array,但最好使用循环,例如:for

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

它也进行了优化(“缓存”数组长度)。如果您想了解更多信息,请阅读我关于该主题的帖子

31赞 Gabriel 5/17/2011 #5

有一种方法可以做到这一点,你的循环中隐式作用域非常小,并消除了额外的变量。

var i = 0,
     item;

// Note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){
    item; // This is the string at the index.
}

或者,如果你真的想得到 id 并有一个非常经典的循环:for

var i = 0,
    len = myStringArray.length; // Cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

现代浏览器都支持迭代器方法、 、 和 Array 原型上的许多其他方法。forEachmapreducefilter

评论

3赞 Phrogz 6/5/2012
请注意,如果代码被调用了足够多的次数,并且它检测到长度没有被循环修改,一些解释器(例如 V8)将自动缓存数组的长度。
0赞 Gabriel 6/26/2012
感谢您提供的信息@Phrogz确实可以进行很多优化,但由于较旧的浏览器没有此功能,因此对其进行优化仍然是最佳做法,因为它非常便宜。
1赞 Stijn de Witt 4/1/2013
@Gabriel:为什么?请举出实际示例,说明不缓存长度实际上是一个性能瓶颈。我遵循“过早优化是万恶之源”的方法。一旦遇到它,我将修复一个实际上会带来问题的循环......
1赞 Gabriel 4/5/2013
@StijndeWitt imo,这只是一个风格问题。老实说,我什至不再使用 for 循环,而是依靠 _.each、_.map 等的下划线来做这些事情。当我编写这样的循环时,我主要缓存了长度,以便我所有的变量声明都集中在一个地方,在我的函数的顶部。在这方面遵循我的建议对任何现实世界的应用都无关紧要。过早的优化是非常糟糕的,但如果优化恰好是由风格决策产生的,我认为这实际上并不重要。
1赞 Noz 7/31/2014
@Gabriel我相信 JavaScript 已经支持数组上的 map 函数,因此无需为此引入额外的库。
70赞 Timo Huovinen 1/5/2012 #6

使用 while 循环...

var i = 0, item, items = ['one', 'two', 'three'];
while(item = items[i++]){
    console.log(item);
}

它记录:“一”、“二”和“三”

对于相反的顺序,一个更有效的循环:

var items = ['one', 'two', 'three'], i = items.length;
while(i--){
    console.log(items[i]);
}

它记录:“三”、“二”和“一”

或者经典循环:for

var items = ['one', 'two', 'three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

它记录:'one','two','three'

参考资料:Google Closure:如何不编写 JavaScript

评论

21赞 Chris Cooper 4/16/2012
如果任何数组元素是伪造的,则“while”语法的第一个示例将不起作用。
2赞 Stijn de Witt 4/1/2013
...而这个 while 循环等价于: for (var i=0,item; item=items[i]; i++) ,它消除了事先声明索引和项目变量的需要......
19赞 kirilloid 4/15/2012 #7

有一种方法可以只遍历自己的对象属性,不包括原型的属性:

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

但它仍然会迭代自定义的属性。

在 JavaScript 中,任何自定义属性都可以分配给任何对象,包括数组。

如果要遍历稀疏数组,则应使用或 with。for (var i = 0; i < array.length; i++) if (i in array)array.forEaches5shim

评论

0赞 Daniel Sokolowski 10/9/2014
那么使用呢?for (var i in array) if (++i)
1201赞 Mark Reed 4/16/2012 #8

是的,假设您的实现包括 for...在 ECMAScript 2015(“Harmony”版本)中引入的功能...如今,这是一个非常安全的假设。

它的工作原理如下:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

或者更好的是,因为 ECMAScript 2015 还提供了块范围的变量:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

(该变量在每次迭代中都不同,但只要不在此处修改,仍然可以在循环体中声明。sconst

关于稀疏数组的说明:JavaScript 中的数组实际上可能存储的项与其报告的一样多;该数字仅比存储值的最高索引大 1。如果数组包含的元素少于其长度所指示的元素,则称其为稀疏。例如,在索引 3、12 和 247 处有一个包含项的数组是完全合法的;这样的数组是 248,尽管它实际上只存储了 3 个值。如果尝试访问任何其他索引处的项,则该数组似乎具有该值,但该数组仍与实际存储了值的数组不同。您可以通过多种方式看到这种差异,例如,在 Node REPL 显示数组的方式中:lengthlengthundefinedundefined

> a              // array with only one item, at index 12
[ <12 empty items>, 1 ]
> a[0]           // appears to have undefined at index 0
undefined
> a[0]=undefined // but if we put an actual undefined there
undefined
> a              // it now looks like this
[ undefined, <11 empty items>, 1 ]

因此,当你想“遍历”一个数组时,你需要回答一个问题:你是想遍历由其长度指示的整个范围,并处理任何缺失的元素,还是只想处理实际存在的元素?这两种方法都有很多应用;这只取决于你使用数组做什么。undefined

如果使用 ..循环访问数组,则循环的主体将执行多次,并且循环控制变量将设置为数组中实际不存在的任何项。根据“执行某些操作”代码的详细信息,该行为可能是您想要的,但如果不是,则应使用其他方法。foroflengthundefined

当然,一些开发人员别无选择,只能使用不同的方法,因为无论出于何种原因,他们的目标是尚不支持 ....forof

只要您的 JavaScript 实现符合以前版本的 ECMAScript 规范(例如,该规范排除了 Internet Explorer 9 之前的版本),就可以使用 Array#forEach 迭代器方法而不是循环。在这种情况下,您需要在数组中的每个项目上传递一个要调用的函数:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

当然,如果你的实现支持 ES6+,你可以使用箭头函数:

myStringArray.forEach( s => { 
     // ... do something with s ...
} );

与 ...不同,它只为数组中实际存在的元素调用函数。如果传递了具有三个元素且长度为 248 的假设数组,它只会调用函数 3 次,而不是 248 次。如果这是您想要处理稀疏数组的方式,那么即使您的解释器支持 ....forof.forEach.forEachforof

最后一个选项适用于所有版本的 JavaScript,是显式计数循环。您只需从 0 数到比长度少 1 的数,然后使用计数器作为索引。基本循环如下所示:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  s = myStringArray[i];
  // ... do something with s ...
}

此方法的一个优点是可以选择如何处理稀疏数组。上面的代码将完整次运行循环的主体,设置为任何缺失的元素,就像 ..;如果您只想处理稀疏数组中实际存在的元素,例如 ,则可以在索引上添加一个简单的测试:lengthsundefinedforof.forEachin

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

根据实现的优化,将长度值分配给局部变量(而不是在循环条件中包含完整表达式)可能会对性能产生重大影响,因为它每次都会跳过属性查找。您可能会看到在循环初始化子句中完成的长度缓存,如下所示:myStringArray.length

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

显式计数循环还意味着您可以根据需要访问每个值的索引。索引也作为额外的参数传递给您传递给的函数,因此您也可以以这种方式访问它:forEach

myStringArray.forEach( (s,i) => {
   // ... do something with s and i ...
});

for...不会给你与每个对象关联的索引,但只要你正在迭代的对象实际上是 的实例(而不是其他可迭代类型之一),你就可以使用 Array#entries 方法将其更改为 [index, item] 对的数组,然后循环访问它:ofArrayforof

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

这。。。其他人提到的语法是用于遍历对象的属性;由于 JavaScript 中的 Array 只是一个具有数字属性名称(以及自动更新的属性)的对象,因此理论上您可以使用它循环访问数组。但问题在于,它并不局限于数值属性值(请记住,即使是方法实际上也只是值为闭包的属性),也不能保证按数字顺序迭代这些属性。因此,...语法不应用于遍历 Arrays。forinlengthforin

评论

24赞 Phrogz 6/5/2012
请注意,如果代码被调用了足够多的次数,并且它检测到长度没有被循环修改,一些解释器(例如 V8)将自动缓存数组的长度。虽然缓存长度仍然很好,但当您的代码被调用足够多的次数以实际发挥作用时,它可能无法提供速度提升。
29赞 Andrew Thomson 4/17/2012 #9

我强烈建议使用 Underscore.js 库。它为您提供了各种函数,可用于遍历数组/集合。

例如:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

评论

7赞 Mark Reed 10/11/2013
对于这个问题的新发现者,我只想指出 Lo-Dash,它是 Underscore 的精神继承者,在许多方面对其进行了改进。
3赞 Walter Chapilliquen - wZVanG 6/24/2015
如果添加了 ECMA-262,为什么要使用甲基。原生代码总是更好。underscoreforEach
12赞 Muhammad Alvin 4/18/2012 #10

它不是 100% 相同,而是相似的:

   var myStringArray = ['Hello', 'World']; // The array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }

评论

1赞 Kzqai 4/18/2012
这似乎会遇到与数组对象的其他 for 类似的问题,因为原型成员变量也会被 for in 捕获。
40赞 Phrogz 6/5/2012 #11

如果你想要一种简洁的方法来编写一个快速循环,你可以反向迭代:

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

这样做的好处是缓存长度(类似于和不同),同时要键入的字符更少。for (var i=0, len=myArray.length; i<len; ++i)for (var i=0; i<myArray.length; ++i)

甚至有些时候你应该反向迭代,比如在迭代期间迭代一个实时的 NodeList 时,你计划在迭代期间从 DOM 中删除项目。

评论

16赞 Stijn de Witt 3/1/2013
对于那些不明白如此巧妙的东西的人来说:首先评估 i-- 表达式,并允许循环在它不是伪造时继续......之后,计数器递减。一旦我变成零,它就会脱离循环,因为零是 Javascript 中的虚假值。
5赞 danwellman 4/27/2013
伪造的?你的意思是假的。让我们都坚持使用正确的术语,以避免混淆;)
21赞 justingordon 10/21/2012 #12

如果您使用的是 jQuery 库,请考虑使用 http://api.jquery.com/jQuery.each/

从文档中:

jQuery.each( collection, callback(indexInArray, valueOfElement) )

返回: 对象

描述:一个通用的迭代器函数,可用于 无缝迭代对象和数组。数组和类数组 具有 Length 属性的对象(例如函数的 arguments 对象) 按数字索引迭代,从 0 到 length-1。其他对象包括 通过其命名属性进行迭代。

该函数与 不同,后者是 用于以独占方式循环访问 jQuery 对象。该函数可用于遍历任何集合,无论是 map(JavaScript 对象)或数组。对于数组, callback 分别传递一个数组索引和一个对应的数组值 时间。(该值也可以通过关键字访问,但 Javascript 将始终将值包装为 一个简单的字符串或数字值。该方法返回其第一个 参数,被迭代的对象。$.each()$(selector).each()$.each()thisthisObject

评论

6赞 Stijn de Witt 4/1/2013
同意,但有例外。不要低估额外依赖项的影响。我建议不要这样做,除非在已经大量使用jQuery的代码中。
2赞 Stijn de Witt 6/5/2017
更新:如今,您可以使用 Array.forEach 来获得与本机数组相同的效果。
22赞 Stijn de Witt 2/28/2013 #13

我还没有看到这种变化,我个人最喜欢它:

给定一个数组:

var someArray = ["some", "example", "array"];

您可以在不访问 length 属性的情况下遍历它:

for (var i=0, item; item=someArray[i]; i++) {
  // item is "some", then "example", then "array"
  // i is the index of item in the array
  alert("someArray[" + i + "]: " + item);
}

请参阅此 JsFiddle 演示: http://jsfiddle.net/prvzk/

这仅适用于稀疏数组。这意味着数组中的每个索引实际上都有一个值。但是,我发现在实践中,我几乎从未在 JavaScript 中使用过稀疏数组......在这种情况下,将对象用作映射/哈希表通常要容易得多。如果你确实有一个稀疏数组,并且想要遍历 0 ..length-1,你需要 for (var i=0; i<someArray.length; ++i) 构造,但你仍然需要一个内部循环来检查当前索引处的元素是否真的被定义了。if

此外,正如 CMS 在下面的评论中提到的,您只能在不包含任何虚假值的数组上使用它。示例中的字符串数组有效,但如果字符串为空,或者数字为 0 或 NaN 等,则循环将过早中断。同样,在实践中,这对我来说几乎从来都不是问题,但这是要记住的事情,这使得在使用它之前要考虑这个问题......这可能会使某些人失去资格:)

我喜欢这个循环的地方是:

  • 写起来很短
  • 无需访问(更不用说缓存)length 属性了
  • 要访问的项目在循环中自动定义 正文。
  • 非常自然地与 array.push 和 array.spice 结合使用列表/堆栈等数组

这样做的原因是数组规范要求,当您从索引 >= 数组的长度中读取项目时,它将返回 undefined。当您写入这样的位置时,它实际上会更新长度。

对我来说,这个结构最接近于我喜欢的 Java 5 语法:

for (String item : someArray) {
}

...还有一个额外的好处,那就是还可以了解环路内的电流索引

评论

14赞 Christian C. Salvadó 3/1/2013
请注意,使用这种方法,循环将在找到错误值(例如空字符串、、、或 )之前停止,甚至在达到长度之前,例如:jsfiddle.net/prvzk/10falseNaNnullundefinedi
3赞 daniel1426 3/20/2014
循环条件可以是 。(item=someArray[i]) !== undefined
9赞 staticd 8/6/2013 #14
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

干净多了......

评论

0赞 Sapphire_Brick 3/17/2020
与 . 相比,这不是很干净。z.forEach(j => console.log(j));
142赞 Marlon Bernardes 8/11/2013 #15

for (const s of myStringArray) {

(直接回答你的问题:现在你可以了!

大多数其他答案都是正确的,但他们没有提到(在撰写本文时)ECMAScript 6 2015 带来了一种新的迭代机制,即 for。的循环。

这种新语法是在 JavaScript 中迭代数组的最优雅的方式(只要你不需要迭代索引)。

它目前适用于 Firefox 13+、Chrome 37+,并且它本身不适用于其他浏览器(请参阅下面的浏览器兼容性)。幸运的是,我们有 JavaScript 编译器(例如 Babel),它允许我们今天使用下一代功能。

它也适用于 Node.js(我在 0.12.0 版本上测试了它)。

迭代数组

// You could also use "let" or "const" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) {
   console.log(letter);
}

迭代对象数组

const band = [
  {firstName : 'John', lastName: 'Lennon'},
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(const member of band){
  console.log(member.firstName + ' ' + member.lastName);
}

迭代生成器:

(示例摘自 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

function* fibonacci() { // A generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (const n of fibonacci()) {
  console.log(n);
  // Truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

兼容性表:http://kangax.github.io/compat-table/es6/#test-for..of_loops

规格:http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}

14赞 Zaheer Ahmed 1/12/2014 #16

优化的方法是缓存数组的长度并使用单个变量模式,使用单个关键字初始化所有变量。var

var i, max, myStringArray = ["Hello", "World"];
for (i = 0, max = myStringArray.length; i < max; i++) {
    alert(myStringArray[i]);

    // Do something
}

如果迭代顺序无关紧要,那么您应该尝试反向循环。它是最快的,因为它减少了开销条件测试,并且递减在一个语句中:

var i,myStringArray = ["item1","item2"];
for (i =  myStringArray.length; i--) {
    alert(myStringArray[i]);
}

或者更好、更干净地使用 while 循环:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // Do something with fruits[i]
}
15赞 molokoloco 3/8/2014 #17

最优雅、最快捷的方式

var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}

http://jsperf.com/native-loop-performance/8


编辑(因为我错了)


比较遍历包含 100000 个项目的数组的方法,并每次对新值执行最小操作。

制备:

<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        // Fake function with minimal action on the value
        var tmp = 0;
        var process = function(value) {
            tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
        };
        
        // Declare the test Array
        var arr = [];
        for (var i = 0; i < 100000; i++)
            arr[i] = i;
    };
</script>

测试:

<a href="http://jsperf.com/native-loop-performance/16" 
   title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>

评论

0赞 Deniz Ozger 3/26/2014
此循环似乎不遵循数组中项的顺序。
0赞 molokoloco 3/28/2014
我的测试是错误的。这是正确的,现在显示所有 LOOPS。jsperf.com/native-loop-performance/16
0赞 Stijn de Witt 5/16/2014
@bergi是对的。此循环在循环遍历数组时擦除数组。在大多数情况下,这不是你想要的。
4赞 njzk2 7/29/2014
破坏虚假项目。
5赞 Sambhav Sharma 5/9/2014 #18

好吧,这个怎么样:

for (var key in myStringArray) {
    console.log(myStringArray[key]);
}

评论

11赞 Matt 5/9/2014
对于数组枚举,不建议使用 for/in 循环,因为不能保证 eumeration 的顺序,并且它枚举属性,而不仅仅是数组元素。有关详细信息,请参阅 stackoverflow.com/questions/500504/...,甚至是此问题的公认答案;stackoverflow.com/a/3010848/444991
0赞 Sambhav Sharma 5/9/2014
好吧,感谢您的更新..当我们不关心数组的顺序时,情况又如何呢?这还会被劝阻吗?
5赞 Matt 5/9/2014
它仍然会不鼓励使用,因为它枚举了所有属性,而不仅仅是数组元素。我链接的两篇文章更详细地解释了这一点。
29赞 RizN81 7/23/2014 #19

在 JavaScript 中,有多种方法可以遍历数组。

通用循环:

var i;
for (i = 0; i < substr.length; ++i) {
    // Do something with `substr[i]`
}

ES5 的 forEach:

substr.forEach(function(item) {
    // Do something with `item`
});

jQuery.each:

jQuery.each(substr, function(index, item) {
    // Do something with `item` (or `this` is also `item` if you like)
});

查看详细信息,或者您也可以检查MDN以在JavaScript中循环访问数组,并使用jQuery检查jQuery。

11赞 Joter 10/21/2014 #20

例如,我在 Firefox 控制台中使用:

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})

可以使用 querySelectorAll 获取相同的结果

document.querySelectorAll('pre').forEach( (e) => { 
   console.log(e.textContent);
})
<pre>text 1</pre>
<pre>text 2</pre>
<pre>text 3</pre>

8赞 Daniel K. 12/12/2015 #21

当然,它效率低下,许多人鄙视它,但它是最接近上述内容之一:

var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
    // Do something
})

评论

3赞 user513951 12/12/2015
这个确切的功能已经是 Mark Reed 答案的一部分。
83赞 John Slegers 3/1/2016 #22

介绍

自从我上大学以来,我就用Java,JavaScript,Pascal,ABAP,PHP,Progress 4GL,C / C++以及其他一些我现在想不起来的语言进行编程。

虽然它们都有自己的语言特性,但这些语言中的每一种都有许多相同的基本概念。这些概念包括过程/函数、-语句、-loops 和 -loops。IFFORWHILE


传统的循环for

传统循环有三个组成部分:for

  1. 初始化:在第一次执行 look 块之前执行
  2. 条件:每次在执行循环块之前检查一个条件,如果为 false,则退出循环
  3. 事后思绪:每次在循环块执行后执行

这三个组件通过符号相互分隔。这三个组件中每个组件的内容都是可选的,这意味着以下内容可能是最小的循环:;for

for (;;) {
    // Do stuff
}

当然,您需要在该 -loop 中包含一个 or 一个 或 一个 ,以使其停止运行。if(condition === true) { break; }if(condition === true) { return; }for

但是,通常情况下,初始化用于声明索引,条件用于将该索引与最小值或最大值进行比较,事后用于递增索引:

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

使用传统循环遍历数组for

循环访问数组的传统方法是:

for (var i = 0, length = myArray.length; i < length; i++) {
    console.log(myArray[i]);
}

或者,如果您更喜欢向后循环,请执行以下操作:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

但是,有许多可能的变体,例如这个:

for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
    console.log(value);
}

...或者这个......

var i = 0, length = myArray.length;
for (; i < length;) {
    console.log(myArray[i]);
    i++;
}

...或者这个:

var key = 0, value;
for (; value = myArray[key++];){
    console.log(value);
}

无论哪种方法最有效,很大程度上取决于个人品味和您正在实施的特定用例。

请注意,所有浏览器都支持这些变体中的每一个,包括非常非常旧的浏览器!


循环while

循环的另一种方法是循环。要遍历数组,您可以这样做:forwhile

var key = 0;
while(value = myArray[key++]){
    console.log(value);
}

与传统循环一样,即使是最古老的浏览器也支持循环。forwhile

另外,请注意,每隔一段时间,循环都可以重写为循环。例如,上面的循环的行为方式与以下 -loop 完全相同:forwhilefor

for(var key = 0; value = myArray[key++];){
    console.log(value);
}

For...infor...of

在 JavaScript 中,您还可以这样做:

for (i in myArray) {
    console.log(myArray[i]);
}

但是,应谨慎使用,因为它在所有情况下的行为都与传统循环不同,并且需要考虑潜在的副作用。请参阅为什么使用“for...in“对于数组迭代是个坏主意?了解更多详情。for

作为...在,现在还有...的。以下示例显示了循环和循环之间的区别:for...offor...in

var myArray = [3, 5, 7];
myArray.foo = "hello";

for (var i in myArray) {
  console.log(i); // logs 0, 1, 2, "foo"
}

for (var i of myArray) {
  console.log(i); // logs 3, 5, 7
}

此外,您需要考虑任何版本的 Internet Explorer 都不支持(Edge 12+ 支持),并且至少需要 Internet Explorer 10。for...offor...in


Array.prototype.forEach()

-loops 的替代方法是 Array.prototype.forEach(),它使用以下语法:for

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

Array.prototype.forEach()所有现代浏览器以及 Internet Explorer 9 及更高版本都支持。


图书馆

最后,许多实用程序库也有自己的变体。AFAIK,最受欢迎的三个是:foreach

jQuery.each(),在 jQuery 中:

$.each(myArray, function(key, value) {
    console.log(value);
});

_.each()在下划线.js中:

_.each(myArray, function(value, key, myArray) {
    console.log(value);
});

_.forEach(),在 Lodash 中:

_.forEach(myArray, function(value, key) {
    console.log(value);
});
9赞 Juanjo Salvador 3/17/2016 #23

简短的回答:是的。你可以这样做:

var myArray = ["element1", "element2", "element3", "element4"];

for (i = 0; i < myArray.length; i++) {
  console.log(myArray[i]);
}

在浏览器控制台中,您可以看到打印的“element1”、“element2”等内容。

13赞 red-o-alf 3/30/2016 #24

如果你想使用jQuery,它的文档中有一个很好的例子:

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });
4赞 user6139250 3/31/2016 #25

最好使用顺序循环:for

for (var i = 0; i < myStringArray.length; i++) {
    // Do something
}

评论

2赞 Sapphire_Brick 9/28/2019
为什么更好?当然,你也可以在 Java 中做到这一点,因为他询问了 foreach 循环。
14赞 Shubham Khatri 4/22/2016 #26

在 JavaScript 中,有几种方法可以做到这一点。前两个示例是 JavaScript 示例。第三个使用JavaScript库,即jQuery使用该函数。.each()

var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
  alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

评论

0赞 brk 12/5/2016
for...in对于类似 Array 的对象,应避免使用
9赞 Amit Jamwal 4/29/2016 #27
var myStringArray = ["hello", "World"];
myStringArray.forEach(function(val, index){
   console.log(val, index);
})
4赞 Dan Chill 5/27/2016 #28
var obj = ["one","two","three"];

for(x in obj){
    console.log(obj[x]);
}
29赞 bzim 8/2/2016 #29

数组循环:

for(var i = 0; i < things.length; i++){
    var thing = things[i];
    console.log(thing);
}

对象循环:

for(var prop in obj){
    var propValue = obj[prop];
    console.log(propValue);
}
13赞 Alongkorn 10/14/2016 #30

在 JavaScript 中,有很多解决方案可以循环数组。

下面的代码是流行的

/** Declare inputs */
const items = ['Hello', 'World']

/** Solution 1. Simple for */
console.log('solution 1. simple for')

for (let i = 0; i < items.length; i++) {
  console.log(items[i])
}

console.log()
console.log()

/** Solution 2. Simple while */
console.log('solution 2. simple while')

let i = 0
while (i < items.length) {
  console.log(items[i++])
}

console.log()
console.log()

/** Solution 3. forEach*/
console.log('solution 3. forEach')

items.forEach(item => {
  console.log(item)
})

console.log()
console.log()

/** Solution 4. for-of*/
console.log('solution 4. for-of')

for (const item of items) {
  console.log(item)
}

console.log()
console.log()

13赞 Espen 10/26/2016 #31

在我看来,最好的方法是使用 Array.forEach 函数。如果你不能使用它,我建议从 MDN 获取 polyfill。要使其可用,这当然是 JavaScript 中迭代数组的最安全方法。

Array.prototype.forEach()

因此,正如其他人所建议的那样,这几乎总是您想要的:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

这确保了在处理数组的范围内所需的任何内容都保持在该范围内,并且您只处理数组的值,而不是对象属性和其他成员,而这正是 in 的作用。for ..

在大多数情况下,使用常规的 C 样式循环是有效的。重要的是要记住,循环中的所有内容都与程序的其余部分共享其作用域,{ } 不会创建新作用域。for

因此:

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

for(var i = 0; i<numbers.length; ++i){
  sum += numbers[i];
}

alert(i);

将输出“11”——这可能是也可能不是你想要的。

一个有效的 jsFiddle 示例:https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/

37赞 Alireza 5/27/2017 #32

是的,你可以在 JavaScript 中使用循环做同样的事情,但不限于此。在 JavaScript 中,有很多方法可以对数组进行循环。想象一下,你下面有这个数组,你想对它做一个循环:

var arr = [1, 2, 3, 4, 5];

这些是解决方案:

1) For 循环

循环是 JavaScript 中循环数组的常用方式,但它不被认为是大型数组的最快解决方案:for

for (var i=0, l=arr.length; i<l; i++) {
  console.log(arr[i]);
}

2) While 循环

while 循环被认为是遍历长数组的最快方法,但它在 JavaScript 代码中通常较少使用:

let i=0;

while (arr.length>i) {
    console.log(arr[i]);
    i++;
}

3) 在 A 做同样的事情时
做,但有一些语法差异,如下所示:
do whilewhile

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

这些是执行 JavaScript 循环的主要方法,但还有更多方法可以做到这一点。

此外,我们还使用循环来循环 JavaScript 中的对象。for in

还要查看 JavaScript 中数组上的 、 、 等函数。他们可能比使用 和 做事更快、更好。map()filter()reduce()whilefor

如果你想了解更多关于 JavaScript 中数组上的异步函数的信息,这是一篇好文章。

函数式编程在 如今的发展世界。这是有充分理由的:功能性 技术可以帮助你编写更多更易于 一目了然地了解、重构和测试。

函数式编程的基石之一是它的特殊用途 列表和列表操作。而这些东西正是 听起来像是:事物的阵列,以及你对它们所做的事情。 但是功能性思维方式对待他们的方式与你略有不同 可能会预料到。

本文将仔细研究我喜欢称之为“大 三“列表操作:map、filter 和 reduce。包住你的头 围绕这三个功能是迈向能够 编写干净的功能代码,并打开通往 强大的函数式和反应式编程技术。

这也意味着你再也不用写for循环了。

阅读更多>>在这里

8赞 Andrii Starusiev 9/3/2017 #33

似乎列出了所有变体,除了 lodashforEach

_.forEach([1, 2], (value) => {
  console.log(value);
});
8赞 BILAL AHMAD 9/14/2017 #34

只需一个简单的单行解决方案:

arr = ["table", "chair"];

// Solution
arr.map((e) => {
  console.log(e);
  return e;
});

评论

4赞 Michel Jung 10/6/2017
您宁愿使用并删除.forEach()return e;
3赞 marpme 11/18/2017
如上所述,该函数用于将某个值映射到其他值,因此我不建议将该值用于此特定示例。mapmap
40赞 Yuci 2/23/2018 #35

在 JavaScript 中以函数式编程方式遍历数组的一些用例:

1. 只需遍历一个数组

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

注意:严格来说,Array.prototype.forEach() 不是一个函数方式,因为它作为输入参数的函数不应该返回一个值,因此不能将其视为纯函数。

2. 检查数组中的任何元素是否通过测试

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3. 转换为新数组

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

注意:map() 方法创建一个新数组,其中包含在调用数组中的每个元素上调用提供的函数的结果。

4. 总结特定属性,并计算其平均值

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5. 在原始数组的基础上创建一个新数组,但不对其进行修改

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6.统计每个类别的数量

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7. 根据特定条件检索数组的子集

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

注意:filter() 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

8. 对数组进行排序

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

enter image description here

9. 在数组中查找元素

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

enter image description here

Array.prototype.find() 方法返回数组中满足所提供测试函数的第一个元素的值。

引用

27赞 colxi 8/21/2018 #36

如果有人对可用于 Array 迭代的多种机制的性能方面感兴趣,我准备了以下 JSPerf 测试:

https://jsperf.com/fastest-array-iterator

Performance results

结果:

传统的迭代器是迄今为止最快的方法,尤其是在缓存数组长度的情况下。for()

let arr = [1,2,3,4,5];

for(let i=0, size=arr.length; i<size; i++){
    // Do something
}

和 方法是最慢的近似值,可能是函数调用开销的结果。Array.prototype.forEach()Array.prototype.map()

评论

0赞 DarckBlezzer 12/11/2018
是更好的使用而不是i = i +1i++
2赞 PowerStat 5/17/2019
可以改进:请使用:++i 而不是 i++,这将避免临时对象。因此,它减少了内存使用和 CPU 时间(无需分配)!
0赞 colxi 5/17/2019
您能提供@PowerStat链接或参考资料吗?我从来没有听说过,听起来很有趣......
1赞 PowerStat 5/18/2019
@colxi 对于这些有趣的事情,您应该阅读 Herb Sutter 和 Scott Meyers 的硬核C++内容。++i 与 i++ 的东西来自这本书:Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions - 我想你也可以在 gotw.ca 上找到它,但可以证明每种编程语言。
3赞 Shijo Rs 10/9/2018 #37

var array = ['hai', 'hello', 'how', 'are', 'you']
$(document).ready(function () {
  $('#clickButton').click(function () {
    for (var i = 0; i < array.length; i++) {
      alert(array[i])
    }
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<input id="clickButton" value="click Me" type="button"/>
<div id="show"></div>

评论

4赞 domdambrogia 3/6/2019
真的有必要将jQuery或HTML引入其中吗?
1赞 Peter Mortensen 10/30/2020
@domdambrogia:这是一个模因
11赞 Sapphire_Brick 8/15/2019 #38

正式的(也许是旧的)方式是:Array.prototype.forEach(...)

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach(function(item, index, _) {
   console.log("[" + index + "] = '" + item + "'");
});

评论

0赞 John Lord 10/24/2020
你的“一些代码”应该有一个例子。目前尚不完全清楚这些变量是直接传入的,还是作为“this”或其他方式传入的。
21赞 Kamil Kiełczewski 12/19/2019 #39

深晦

let a= ["Hello", "World"];

while(a.length) { console.log( a.shift() ); }

性能测试

今天(2022-11-13),我在Chrome 107、Safari 15.2和Firefox 106上对选定的解决方案进行了测试。

结论

  • 解决方案 C 和 D 在所有浏览器上都快或最快,适用于所有数组。
  • 解决方案 A 和 B 在所有浏览器上对所有数组都是最慢的

结果

enter image description here

我执行 3 个测试:

  • small - 对于 2 个元素数组(如 OP) - 你可以在这里运行它
  • medium - 用于 10K 元素数组和 - 您可以在此处运行它
  • big - 对于 100K 元素数组 - 你可以在这里运行它

以下代码片段显示了测试中使用的代码。

function A(a) {
  let r=0;
  while(a.length) r+= a.shift().length;
  return r;
}

function B(a) {
  let r=0;
  for(i in a) r+= a[i].length;
  return r;
}

function C(a) {
  let r=0;
  for(x of a) r+= x.length;
  return r;
}

function D(a) {
  let r=0;
  for (i=0; i<a.length; ++i) r+= a[i].length;
  return r;

}

function E(a) {
  let r=0;
  a.forEach(x=> r+= x.length);
  return r;
}

let arr= ["Hello", "World!"];
[A,B,C,D,E].forEach(f => console.log(`${f.name}: ${f([...arr])}`))

以下是中型阵列的 Chrome 示例结果:

enter image description here

评论

0赞 Sapphire_Brick 1/16/2020
这就是 Haskell-y 的方式;继续服用第一个。聪明,但可能很慢。
0赞 Kamil Kiełczewski 7/24/2020
@Sapphire_Brick实际上它非常快 - 这是测试
4赞 Sapphire_Brick 8/5/2020
你说得很对。我使用包含 1000 个项目的数组运行了您的示例,并且速度大约是版本的两倍。¯\_(ツ)_/¯while(a.length) { console.log(a.shift()); }for(var i = 0; i < a.length; i++) { console.log(a[i]); }
3赞 Peter Mortensen 10/30/2020
即使它没有出现在你的母语中,你也不应该遗漏英文冠词(不定冠词(“a”或“an”)和定冠词(“the”))。例如,参见英文文章 - 修复常见语法错误和错误的 3 条简单规则和 A, AN, THE - 英文文章
2赞 Kamil Kiełczewski 3/1/2021
@Pitouli你是对的 - 我将答案回滚到其初始形式。当我有更多时间时,我会再次进行基准测试
5赞 kabirbaidhya 9/21/2020 #40

JavaScript 中的数组遍历备忘单

给定一个数组,您可以通过以下多种方式之一遍历它。

1. 经典的for循环

const myArray = ['Hello', 'World'];

for (let i = 0; i < myArray.length; i++) {
  console.log(myArray[i]);
}

2. 为了...之

const myArray = ['Hello', 'World'];

for (const item of myArray) {
  console.log(item);
}

3. 数组.prototype.forEach()

const myArray = ['Hello', 'World'];

myArray.forEach(item => {
  console.log(item);
});

4. while 循环

const myArray = ['Hello', 'World'];
let i = 0;

while (i < myArray.length) {
  console.log(myArray[i]);
  i++;
}

5. 做...while 循环

const myArray = ['Hello', 'World'];
let i = 0;

do {
  console.log(myArray[i]);
  i++;
} while (i < myArray.length);

6. 队列样式

const myArray = ['Hello', 'World'];


while (myArray.length) {
  console.log(myArray.shift());
}

7. 堆栈样式

注意:在此列表中,列表是反向打印的。

const myArray = ['Hello', 'World'];

while (myArray.length) {
  console.log(myArray.pop());
}

评论

0赞 Aleksandr Golovatyi 6/17/2021
“for” 和 “for in” 循环创建额外的变量,“forEach” - 创建额外的函数上下文。我认为最好的方法是“为了”。
10赞 TheComputerWizard 11/28/2020 #41
//Make array
var array = ["1","2","3","4","5","6","7","8","9","10"]
//Loop
for(var i = 0; i < array.length; i++){
 console.log((i+1) + " --> " + array[i])
}

对于 的 实际数字,如果需要,需要更改为 或 。
希望这有帮助。
i(i+1)i(i)

101赞 Satish Chandra Gupta 6/5/2021 #42

6 种不同的方法来遍历数组

您可以通过许多不同的方法遍历数组。我从上到下整理了我最喜欢的 6 种方法。

1.使用 JavaScript for 循环

当它只是循环遍历一个数组时,循环是我的首选。for

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

2.使用 forEach 循环

forEachloop 是一种遍历数组的现代方法。此外,它还提供了更大的灵活性和对数组和元素的控制。

let array = [1, 2, 3, 4, 5];
array.forEach((element) => {
  console.log(element);
});

3.用于...之

for...ofloop 使您可以直接访问数组元素。

let array = [1, 2, 3, 4, 5];
for (let element of array) {
  console.log(element);
}

4.用于...在循环中

for...in为您提供一个键,您可以使用该键访问数组元素。

let array = [1, 2, 3, 4, 5];
for(let index in array){
  console.log(array[index]);
}

5.使用 while 循环

while loop 也可用于遍历数组。

let array = [1, 2, 3, 4, 5];
let length = array.length;
while(length > 0){
  console.log(array[array.length - length]);
  length--;
}

6.使用do...while 循环

同样,我使用循环do...while

let array = [1, 2, 3, 4, 5];
let length = array.length;
do {
  console.log(array[array.length - length]);
  length--;
}
while (length > 0)

21赞 Aleksandr Golovatyi 6/15/2021 #43

数组迭代有 4 种方式:

// 1: for

for (let i = 0; i < arr.length; ++i) {
  console.log(arr[i]);
}

// 2: forEach

arr.forEach((v, i) => console.log(v));

// 3: for in

for (let i in arr) {
  console.log(arr[i]);
}

// 4: for of

for (const v of arr) {
  console.log(v);
}

摘要:1 和 3 解决方案创建额外的变量,2 - 创建额外的函数上下文。最好的方式是第 4 个 - “为了”。

评论

2赞 YesItsMe 8/3/2021
您是否愿意详细说明为什么 4 个“for of”比其他“更好
1赞 Aleksandr Golovatyi 8/3/2021
它不会创建不必要的变量或函数上下文。但是,如果您不关心小缺点,则可以使用其中任何一个,哪个对您来说更舒服。@YesItsMe 谢谢你的提问。
0赞 Alfredo Rahn Linde 11/10/2021 #44

考虑一下:

const ITEMS = ['One','Two','Three']
let item=-1

//Then, you get looping with every call of:

ITEMS[item=item==ITEMS.length-1?0:item+1]
7赞 Arun s 8/5/2022 #45

在 javascript 中有多种方法可以做到这一点。以下是处理数组的常用方法。

方法1:

const students = ["Arun","Jos","John","Kiran"]
for (var index = 0; index < students.length; index++) {
  console.log(students[index]);
}

方法2:

students.forEach((student, index) => console.log(student));

方法3:

for (const student of students) {
      console.log(student);
}
  
-1赞 Tom Bombadil 10/23/2022 #46

这个答案提供了循环和数组函数的替代方法,用于遍历数组。

在某些情况下,使用递归实现而不是传统的循环和回调是有意义的。特别是,如果您必须使用多个数组或嵌套数组。您可以避免编写嵌套循环来访问来自多个数组的数据。我还发现这段代码更易于阅读和编写。

/**
  array is the array your wish to iterate. 
  response is what you want to return.
  index increments each time the function calls itself.
**/

const iterateArray = (array = [], response = [], index = 0) => {
    const data = array[index]

    // If this condition is met. The function returns and stops calling itself.
    if (!data) {
      return response
    }
    // Do work...
    response.push("String 1")
    response.push("String 2")

    // Do more work...

    // THE FUNCTION CALLS ITSELF
    iterateArray(data, response, index+=1)
}

const mainFunction = () => {
    const text = ["qwerty", "poiuyt", "zxcvb"]

    // Call the recursive function
    const finalText = iterateArray(text)
    console.log("Final Text: ", finalText()
}

假设数组被传递给包含的对象而不是字符串。每个对象都包含另一个数组。您必须运行嵌套循环才能访问内部数组,但如果以递归方式迭代,则不会。iterateArray

你也可以做出承诺。iterateArray

const iterateArray = (array = [], response = []) =>
  new Promise(async (resolve, reject) => {
    const data = array.shift()
    // If this condition is met, the function returns and stops calling itself.
    if (!data) {
      return resolve(response)
    }

    // Do work here...

    const apiRequestData = data.innerArray.find((item) => {
      item.id === data.sub_id
    })

    if (apiRequestData) {
      try {
        const axiosResponse = await axios.post(
          "http://example.com",
          apiRequestData
        )
        if (axiosResponse.status === 200) {
          response.push(apiRequestData)
        } else {
          return reject("Data not found")
        }
      } catch (error) {
        reject(error)
      }
    } else {
      return reject("Data not found")
    }
    // THE FUNCTION RESOLVES AND CALLS ITSELF
    resolve(iterateArray(data, response))
  })