在JavaScript中遍历数组(for each循环)

5654

如何使用JavaScript循环遍历数组中的所有条目?


使用 for...of 循环。请参阅 https://www.w3schools.com/JS/js_loop_forof.asp。 - user19690494
与“如何在JavaScript中循环遍历数组”几乎相同,但略微更为通用的内容。 - outis
41个回答

18

我也想将这个作为一个反向循环和上面的答案的组成部分,供那些也喜欢这种语法的人使用。

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

优点:

这种方法的好处是:你已经在第一行中有了一个引用,不需要在之后的另一行中再次声明。当遍历对象数组时非常方便。

缺点:

这种方法会在引用为假(undefined等)时出错。但是它也可以被用作优势。然而,这会使它变得更难读懂。而且,根据浏览器的不同,它可能没有原始方法快速地执行。


12

使用 $.map 的jQuery方法:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

11

使用ECMAScript 6的循环解构展开运算符

对于ECMAScript 6的新手来说,解构和展开运算符已被证明非常有用,因为它更具人类可读性/美学,尽管一些JavaScript老手可能认为它很混乱。初学者或其他人可能会发现它有用。

以下示例将使用 for...of语句和 .forEach方法。

示例6、7和8可与任何函数式循环一起使用,如 .map, .filter, .reduce, .sort, .every, .some。有关这些方法的更多信息,请查看Array对象

示例1:普通的 for...of 循环 - 没有什么技巧。

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

示例 2:将单词拆分为字符

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);
}

示例 3:使用keyvalue循环

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type:
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on Internet Explorer  unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

示例4:内联获取对象属性

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

示例 5:获取所需对象的深层属性

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

例子6: .forEach 方法能够与 例子3 一起使用吗?

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

例子 7: .forEach 方法可以与 例子 4 一起使用。

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions
// are required to be surrounded by parentheses
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

示例8: .forEach 方法是否可与 示例5 一起使用?

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});


11

概述:

在遍历数组时,我们通常希望实现以下目标之一:

  1. 我们想遍历数组并创建一个新的数组:

    Array.prototype.map

  2. 我们想遍历数组而不创建一个新的数组:

    Array.prototype.forEach

    for..of loop

在JavaScript中,有许多方法可以完成这两个目标。然而,有些比其他方法更方便。下面是一些在JavaScript中使用最广泛、最方便的方法来实现数组迭代。

创建新数组:Map

map() 是位于 Array.prototype 上的函数,它可以转换数组的每个元素,然后返回一个新的数组。map() 接受回调函数作为参数,按照以下方式工作:

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

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

我们传递给map()作为参数的回调函数将被执行每个元素,然后返回一个与原始数组长度相同的数组。在这个新的数组中,每个元素都会通过作为map()参数传递的回调函数进行转换。

map和其他循环机制(如forEachfor..of循环)之间的明显区别在于map返回一个新数组并保留旧数组不变(除非您使用像splice这样的方法显式地对其进行操作)。

此外,请注意map函数的回调提供了当前迭代的索引号作为第二个参数。第三个参数提供map被调用的数组。有时这些属性可以非常有用。

使用forEach循环

forEach是位于Array.prototype上的函数,它接受一个回调函数作为参数。然后针对数组中的每个元素执行此回调函数。与map()函数相比,forEach函数不返回任何内容(undefined)。例如:

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

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

map 函数类似,forEach 回调函数提供当前迭代的索引编号作为第二个参数。同时,第三个参数是否提供了调用 forEach 的数组?

使用 for..of 循环遍历元素

for..of 循环遍历数组(或任何其他可迭代对象)的每个元素。它按照以下方式工作:

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

for(let element of arr) {
  console.log(element * 2);
}

在上面的示例中,element代表一个数组元素,而arr是我们想要循环的数组。注意,名称element是任意的,我们也可以选择其他名称,例如'el'或者更具有描述性的名称,当适用时。

不要将for..in循环和for..of循环混淆。 for..in将循环遍历数组的所有可枚举属性,而for..of循环则只会遍历数组元素。例如:

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

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}


10

性能

今天(2019年12月18日),我在我的macOS v10.13.6(High Sierra)上进行了测试,使用的浏览器是Chrome v79.0、Safari v13.0.4和Firefox v71.0(64位)。关于优化(以及通常不值得引入到代码中的微小优化,因为收益很小,但代码复杂度增加)的结论。

  • 看起来传统的for i (Aa)是在所有浏览器上编写快速代码的不错选择。

  • 其他解决方案,如for-of (Ad),都在组C中。通常比Aa慢2-10倍(甚至更多),但对于小数组而言,可以使用它,以增加代码清晰度。

  • 循环中缓存了数组长度n (Ab, Bb, Be)有时更快,有时则不一定。编译器可能会自动检测到这种情况并引入缓存。缓存和非缓存版本(Aa, Ba, Bd)之间的速度差异约为~1%,因此引入n是一种微优化

  • 类似i--的解决方案,其中循环从最后一个数组元素开始(Ac, Bc),通常比正向解决方案慢约30% - 可能的原因是CPU内存缓存工作的方式-正向内存读取对于CPU缓存更为优化)。建议不要使用这样的解决方案。

在测试中,我们计算数组元素的总和。我对小数组(10个元素)和大数组(1M个元素)进行了测试,并将它们分为三组:

  • A - for 循环测试
  • B - while 循环测试
  • C - 其他/替代方法

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
//let arr = Array.from(Array(1000000), (x, i) => i%10);

function Aa(a, s=0) {
  for(let i=0; i<a.length; i++) {
    s += a[i];
  }
  console.log('Aa=', s);
}

function Ab(a, s=0) {
  let n = a.length;
  for(let i=0; i<n; i++) {
    s += a[i];
  }
  console.log('Ab=', s);
}

function Ac(a, s=0) {
  for(let i=a.length; i--;) {
    s += a[i];
  }
  console.log('Ac=', s);
}

function Ad(a, s=0) {
  for(let x of a) {
    s += x;
  }
  console.log('Ad=', s);
}

function Ae(a, s=0) {
  for(let i in a) if (a.hasOwnProperty(i)) {
    s += a[i];
  }
  console.log('Ae=', s);
}

function Ba(a, s=0) {
  let i = -1;
  while(++i < a.length) {
    s+= a[i];
  }
  console.log('Ba=', s);
}

function Bb(a, s=0) {
  let i = -1;
  let n = a.length;
  while(++i < n) {
    s+= a[i];
  }
  console.log('Bb=', s);
}

function Bc(a, s=0) {
  let i = a.length;
  while(i--) {
    s += a[i];
  }
  console.log('Bc=', s);
}

function Bd(a, s=0) {
  let i = 0;
  do {
    s+= a[i]
  } while (++i < a.length);
  console.log('Bd=', s);
}

function Be(a, s=0) {
  let i = 0;
  let n = a.length;
  do {
    s += a[i]
  } while (++i < n);
  console.log('Be=', s);
}

function Bf(a, s=0) {
  const it = a.values(); 
  let e;
  while (!(e = it.next()).done) { 
    s+= e.value; 
  }
  console.log('Bf=', s);
}

function Ca(a, s=0) {
  a.map(x => { s+=x });
  console.log('Ca=', s);
}

function Cb(a, s=0) {
  a.forEach(x => { s+=x });
  console.log('Cb=', s);
}

function Cc(a, s=0) {
  a.every(x => (s += x, 1));
  console.log('Cc=', s);
}

function Cd(a, s=0) {
  a.filter(x => { s+=x });
  console.log('Cd=',s);
}

function Ce(a, s=0) {
  a.reduce((z, c) => { s+=c }, 0);
  console.log('Ce=', s);
}

function Cf(a, s=0) {
  a.reduceRight((z, c) => { s += c }, 0);
  console.log('Cf=', s);
}

function Cg(a, s=0) {
  a.some(x => { s += x } );
  console.log('Cg=', s);
}

function Ch(a, s=0) {
  Array.from(a, x=> s += x);
  console.log('Cc=', s);
}


Aa(arr);
Ab(arr);
Ac(arr);
Ad(arr);
Ae(arr);

Ba(arr);
Bb(arr);
Bc(arr);
Bd(arr);
Be(arr);
Bf(arr);

Ca(arr);
Cb(arr);
Cc(arr);
Cd(arr);
Ce(arr);
Cf(arr);
Cg(arr);
Ch(arr);
<p style="color: red">This snippets only PRESENTS code used for benchmark - it not perform test itself</p>

跨浏览器结果

所有测试浏览器的结果

输入图像描述浏览器**

包含10个元素的数组

Chrome的结果。您可以在此处执行测试。

Enter image description here

拥有1,000,000个元素的数组

Chrome浏览器的测试结果。您可以在您的计算机上执行此测试here

Enter image description here


9

最接近你想法的方法是使用Array.forEach(),它接受一个闭包函数,该函数将对数组的每个元素执行。

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

另一种可行的方法是使用 Array.map(),它的工作方式相同,但是它还会把你返回的所有值都放到一个新数组中(从本质上将每个元素映射到一个新元素),像这样:

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]

9
根据新的更新功能 ECMAScript 6 (ES6) 和 ECMAScript 2015,您可以在循环中使用以下选项:

for 循环

for(var i = 0; i < 5; i++){
  console.log(i);
}

// Output: 0,1,2,3,4

for...in循环

let obj = {"a":1, "b":2}

for(let k in obj){
  console.log(k)
}

// Output: a,b

Array.forEach()

let array = [1,2,3,4]

array.forEach((x) => {
  console.log(x);
})

// Output: 1,2,3,4

for...of循环

let array = [1,2,3,4]

for(let x of array){
  console.log(x);
}

// Output: 1,2,3,4

while循环

let x = 0

while(x < 5){
  console.log(x)
  x++
}

// Output: 1,2,3,4

do...while循环

let x = 0

do{
  console.log(x)
  x++
}while(x < 5)

// Output: 1,2,3,4

8

lambda语法通常在Internet Explorer 10或以下版本中不起作用。

我通常使用

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

如果你是一个jQuery的爱好者并且已经有了一个运行的jQuery文件,你需要颠倒索引和值参数的位置。
$("#ul>li").each(function(**index, value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

8
你可以这样调用forEach: forEach会迭代你提供的数组,对于每次迭代,它都会有一个 element 变量来保存该次迭代的值。如果你需要索引,可以通过将 i 作为第二个参数传递给forEach的回调函数来获取当前索引。
ForEach基本上是一种高阶函数,它以另一个函数作为其参数。
let theArray= [1,3,2];

theArray.forEach((element) => {
  // Use the element of the array
  console.log(element)
}

输出:

1
3
2

您也可以像这样遍历数组:
for (let i=0; i<theArray.length; i++) {
  console.log(i); // i will have the value of each index
}

7
如果您想使用箭头函数循环遍历一个对象数组:

let arr = [{name:'john', age:50}, {name:'clark', age:19}, {name:'mohan', age:26}];

arr.forEach((person)=>{
  console.log('I am ' + person.name + ' and I am ' + person.age + ' old');
})


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接