在 JavaScript 中循环遍历数组

新手上路,请多包涵

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

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

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

原文由 Mark Szymanski 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 580
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 });

正确使用 reduce

 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);
}

优点

  • 它可以迭代各种各样的对象。
  • 可以使用正常的流量控制语句( break / continue )。
  • 用于迭代串行异步值。

缺点

不要使用 for...in

@zipcodeman 建议使用 for...in 语句,但对于迭代数组 for-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 方法允许您仅枚举 _自己的属性_。就是这样,只有对象物理上具有的属性,没有继承的属性。

我建议您阅读以下文章:

原文由 Christian C. Salvadó 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题