如何使用JavaScript循环遍历数组中的所有条目?
如何使用JavaScript循环遍历数组中的所有条目?
我也想将这个作为一个反向循环和上面的答案的组成部分,供那些也喜欢这种语法的人使用。
var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
console.log(item);
}
优点:
这种方法的好处是:你已经在第一行中有了一个引用,不需要在之后的另一行中再次声明。当遍历对象数组时非常方便。
缺点:
这种方法会在引用为假(undefined等)时出错。但是它也可以被用作优势。然而,这会使它变得更难读懂。而且,根据浏览器的不同,它可能没有原始方法快速地执行。
使用 $.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];
对于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:使用key
和value
循环
// 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);
});
在遍历数组时,我们通常希望实现以下目标之一:
我们想遍历数组并创建一个新的数组:
Array.prototype.map
我们想遍历数组而不创建一个新的数组:
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
和其他循环机制(如forEach
和for..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);
}
今天(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个元素)进行了测试,并将它们分为三组:
for
循环测试while
循环测试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的结果。您可以在此处执行测试。
拥有1,000,000个元素的数组
Chrome浏览器的测试结果。您可以在您的计算机上执行此测试here
最接近你想法的方法是使用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]
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
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);
});
$("#ul>li").each(function(**index, value**){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
forEach
会迭代你提供的数组,对于每次迭代,它都会有一个 element
变量来保存该次迭代的值。如果你需要索引,可以通过将 i
作为第二个参数传递给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
}
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');
})