协慌网

登录 贡献 社区

在 JavaScript 中循环遍历数组

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

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

你能用 JavaScript 做同样的事吗?

答案

使用顺序for循环:

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

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

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

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

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

例如:

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

for (var i in array) {
  alert(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...
    alert("prop: " + prop + " value: " + obj[prop])
  }
}

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

我建议你阅读以下文章:

是的,但只有当你实现包括for ... of中介绍的特征的 ECMAScript 2015 年 (以下简称 “和谐” 版本)。

它的工作原理如下:

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

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

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

然而,许多 JavaScript 开发人员仍然在一个尚未出现的环境中工作 - 特别是如果编写代码以在 Web 浏览器中运行,那么网站开发人员通常无法确定他们的客户将使用哪种浏览器 / 版本。

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

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

但是,如果即使这样做太多了,而且你想要的东西适用于所有版本的 JavaScript,那么你必须使用一个显式的计数循环。最安全的版本,正确处理稀疏数组,如下所示:

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表达式相反)可以在性能上产生显着差异,因为它每次都会跳过属性查找; 在我的机器上使用 Rhino,加速比为 43%。

您将经常在循环初始化子句中看到完成的长度缓存,如下所示:

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

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

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

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

一般语法是:

array.map(func)

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

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