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

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

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


当前回答

是的,假设您的实现包括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

(变量s在每次迭代中都是不同的,但只要不在循环体中修改,它仍然可以在循环体内部声明为常量。)

关于稀疏数组的一个注意事项:JavaScript中的数组实际存储的项目可能不像其长度所报告的那么多;该数字仅比存储值的最高索引大一个。如果数组包含的元素少于其长度所指示的元素,则称为稀疏。例如,只有索引3、12和247处的项的数组是完全合法的;这种数组的长度是248,尽管它实际上只存储3个值。如果您试图访问任何其他索引处的项,则该数组将显示为具有未定义的值,但该数组与实际存储有未定义值的数组不同。您可以从许多方面看到这种差异,例如,在Node REPL显示阵列的方式中:

> 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 ]

因此,当您想要“循环遍历”数组时,您需要回答一个问题:是要在其长度所指示的整个范围内循环,并为任何缺失的元素处理未定义的元素,还是只处理实际存在的元素?这两种方法都有大量的应用;这取决于您使用数组的目的。

如果使用for..遍历数组。。中,循环的主体执行长度次,并且对于数组中实际不存在的任何项,循环控制变量设置为undefined。根据“使用”代码的细节,这种行为可能是您想要的,但如果不是,您应该使用不同的方法。

当然,有些开发人员别无选择,只能使用不同的方法,因为无论出于什么原因,他们的目标是一个尚不支持的JavaScript版本。。。属于

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

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

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

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

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

最后一个选项是显式计数循环,适用于所有版本的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 ...
}

这种方法的一个优点是可以选择如何处理稀疏数组。上面的代码将运行循环体的整个长度,对于任何缺失的元素,s都设置为undefined,就像for。。属于如果您希望只处理稀疏数组中实际存在的元素,例如.forEach,则可以在索引上添加一个简单的in测试:

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

对于of不会为您提供与每个对象关联的索引,但只要您正在迭代的对象实际上是Array的实例(而不是..of的其他可迭代类型之一),您就可以使用Array#entries方法将其更改为[index,item]对的数组,然后对其进行迭代:

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

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

其他回答

优化的方法是缓存数组长度,并使用单变量模式,用一个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]
}

有一种方法可以只迭代自己的对象财产,而不包括原型的属性:

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

但它仍将迭代自定义的财产。

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

如果要在稀疏数组上迭代,应使用for(var i=0;i<array.length;i++)If(i in array)或array.forEach with es5shim。

有多种方法可以在javascript中实现。下面是处理数组的常用方法。

方法1:

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

方法2:

students.forEach((学生,索引)=>console.log(学生));

方法3:

for (const student of students) {
      console.log(student);
}
  

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

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

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

阵列迭代有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-创建额外的函数上下文。最好的方式是第四位-“for of”。