JS实用功能-10、遍历数组for vs for-in vs forEach() vs for-of
下面给大家讲讲JS中常用的四种数组遍历的方法,并做一下对比。
四种常用的方法如下:
let someArray = [1,2,3,4]; //for循环 for(let i = 0; i < someArray.length; i++){ const elem = someArray[i]; //... } //for-in循环 for (const key in someArray) { console.log(key); } //数组原生 forEach someArray.forEach((element, index) => { console.log(element, index); }); //for-of循环 for (const iterator of someArray) { console.log(iterator); }
但for-of是最佳选择,下面我们来具体分析一下。
一、for循环
for是JavaScript中的普通循环。它已存在于ECMAScript 1中。此for循环记录以下各项的每个元素的索引和值arr:const arr = ['a', 'b', 'c']; arr.prop = 'property value'; for(let i = 0; i < arr; i++){ const elem = arr[i]; console.log(elem, i); } //输出: //0, 'a' //1, 'b' //2, 'c'
说说此循环的优缺点:
它非常通用,但是当我们要做的是遍历数组时,也很麻烦。 如果我们不想从第一个Array元素开始循环,它仍然很有用。没有其他的循环机制可以让我们做到这一点。二、for-in循环
for-in循环跟为for循环年代一样久远,在ECMAScript1中就有for-in循环记录。//... for (const key in arr) { console.log(key); } //输出: //'0' //'1' //'2' //'prop'for-in 不是遍历数组的好选择: 1.它访问属性键,而不是值。 2.作为属性键,数组元素的索引是字符串,而不是数字。 3.它访问所有可枚举的属性键(自己的和继承的),而不仅仅是Array元素的那些。 for-in访问继承的属性确实有一个用例:遍历对象的所有可枚举属性。但是即使在这里,我还是希望手动遍历原型链,因为您拥有更多控制权。
三、数组的forEach方法
考虑到两者for都不for-in是特别适合循环遍历数组,ECMAScript 5中引入了一个辅助方法Array.prototype.forEach():arr.forEach((elem, index) => { console.log(elem, index); }); //输出: //'a', 0 //'b', 1 //'c', 2此方法确实很方便:它使我们无需执行大量操作即可访问Array元素和Array元素索引。箭头函数(在ES6中引入)使该方法在语法上更加优雅。 forEach函数的主要缺点: 1.您不能await在这种循环的“主体”中使用。 2.您不能.forEach()提早结束循环。在for循环中,我们可以使用break。
三(1)、可以提前结束的forEach方法
有一种解决方法,如果您要使用类似循环.forEach()并提早结束:.some()还循环所有Array元素,并在其回调返回真值时停止。const color = ['red', 'green', 'blue']; color.some((elem, index) => { if(index > 2){ return true; //结束循环 } console.log(elem); //此回调隐式返回“undefined”,这是一个错误的值。因此,循环仍在继续。 }); //输出: //'red' //'green'可以说,这是对.some()的滥用,我不确定理解此代码(与for-of和相比break)有多么容易。
四、for-of循环
ES6中的循环法。for (const elem of arr) { console.log(elem); } //输出: //'a' //'b' //'c'for-of 对于遍历数组非常有效: 1.遍历数组元素。 2.我们可以使用await。 3.我们甚至可以将–break和continue用于外部范围.
四(1)、for-of和迭代对象
for-of的另一个好处是,我们不仅可以遍历数组,还可以遍历任何可迭代对象,例如遍历Maps:const myMap = new Map() .set(false, 'no') .set(true, 'yes'); for (const elem of myMap) { console.log(key, value); } //输出: //false, 'no' //true, 'yes'迭代myMap产生[key,value]对,我们对其进行解构以直接访问每个对的组件。
四(2)、for-of和数组索引
Array方法.keys()返回Array的索引上的可迭代对象:const snacks = ['巧克力', '草莓', '香草']; for (const index of snacks.keys) { console.log(index); } //输出: //0 //1 //2
四(3)、for-of和数组的entries方法
Array方法.entries()返回[index,value]对上的可迭代对象。如果使用for-of此方法并对其进行销毁,则可以方便地访问索引和值://... for (const [index, value] of snacks.entries) { console.log(index, value); } //输出: //0, '巧克力' //1, '草莓' //2, '香草'四种循环机制之间的性能差异通常应该无关紧要。但是可以从方法的限制和多用方面考虑使用。