数组作为JavaScript里面最强大的数据类型,在很多情况下,我们都要对不同格式的数组进行数据提取,这就避不开对数组进行遍历,本篇博客我将整理出大量的遍历数组的方法
循环遍历
for循环
用for循环遍历数组是最基本的一种遍历方式,这种方式同样适用于类数组的遍历。代码展示如下:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
这里主要是运用了数组和类数组中都存在的length属性加上索引的方式实现的对数组的遍历
while循环
用fwhile循环遍历数组是最基本的一种遍历方式,这种方法和for循环实现思路基本一致。代码展示如下:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var i = 0
while (i < arr.length) {
console.log(arr[i]);
i++
}
for…in循环
for...in循环本来是遍历对象的方法,但是数组最为一种特殊的对象,也可以使用该循环方式,代码展示如下:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for (var key in arr) {
console.log(arr[key]);
}
上述代码使用了for…in循环遍历数组arr,并在每次迭代中打印出当前元素的值。然而,在JavaScript中,for…in循环用于对象的遍历,而不是专门用于数组的遍历。因此,尽管它可以遍历数组,但它也会遍历数组原型链上的可枚举属性。虽然for…in循环能够获取到数组的索引,但它在某些情况下可能会导致意外的行为,比如遍历到原型链上的属性或方法。建议使用其他适合数组遍历的方式,比如for循环、forEach、map等方法。
for…of循环
for...of循环本来是遍历对象的方法,和for...in的关系用法在数组中基本一致,代码展示如下:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for (var key of arr) {
console.log(key);
}
上述代码使用了for…of循环来遍历数组arr,并在每次迭代中打印出当前元素的值。在JavaScript中,for…of循环提供了一种简洁、直观的方式来遍历可迭代对象,包括数组。与for…in循环不同,for…of循环专门用于遍历集合(如数组、字符串、Map、Set等)中的元素,而不会遍历它们的原型链。因此,在大多数情况下,for…of循环是遍历数组时的首选方法之一。
方法遍历
keys() ; value() ; entries()
在 JavaScript 中,Array.prototype.values(), Array.prototype.keys(), 和 Array.prototype.entries() 方法分别返回一个新的 Array Iterator 对象,这个对象包含数组中每个索引的值、键(即索引),或者是键值对。
使用 console.log() 直接输出这些迭代器可能不会显示所有详细信息,因为它们并不是普通的数组,而是特殊的对象。如果你尝试在浏览器控制台或 Node.js 环境中运行这些代码行,你将得到以下类似的输出:
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].values()); // Array Iterator {}
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].keys()); // Array Iterator {}
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].entries()); // Array Iterator {}
要查看这些迭代器内容,你需要使用循环(比如 for...of 循环)来遍历它们:
for (let value of [1, 2, 3, 4, 5, 6, 7, 8, 9].values()) {
console.log(value);
}
for (let key of [1, 2, 3, 4, 5, 6, 7, 8, 9].keys()) {
console.log(key);
}
for (let entry of [1, 2, 3, 4, 5, 6, 7, 8, 9].entries()) {
console.log(entry);
}
forEach()
forEach方法:arr.forEach((item,index,array) =>{},thisArgs)
forEach方法不会改变原数组,该方法没有返回值
forEach遍历数组时,是改变引用数据类型的数据时,会同步修改
除了第一个参数传回调函数以外,第二个参数可以用于指定改函数运行时的上下文环境,即可以修改函数的this指向,指向第二个参数
var arr = [1, 2, 3, 4, 5]
arr.forEach((item, index, array) => {
item *= 10
})
console.log(arr)
var list = [
{ id: 0 },
{ id: 1 },
{ id: 2 }
]
list.forEach((item, index, array) => {
item.id += 10
})
console.log( list)
arr.forEach((item, index, array) => {
console.log(this)
},{name:"asd"})
传递了第二个参数{name:“asd”},该参数是指定函数运行时的上下文环境(即this的指向)。在这里,console.log(this)会打印出{name:“asd”},因为我们显式地将this指向了{name:“asd”};后续map、filter、some、every的第二个参数和该方法的用法一致
map()
map方法:arr.map((item,index,array) =>{ return 返回值 },thisArgs)
map方法不会改变原数组,该方法 有 返回值,返回值是每个回调函数中的返回值组成的数组
map遍历数组时,是改变引用数据类型的数据时,会同步修改
除了第一个参数传回调函数以外,第二个参数可以用于指定改函数运行时的上下文环境,即可以修改函数的this指向,指向第二个参数
var arr = [1, 2, 3, 4, 5]
var i = arr.map((item, index, array) => {
item *= 10
return item
})
console.log("🚀 ~ i ~ i:", i)
console.log("🚀 ~ arr:", arr)
arr.map((item, index, array) => {
console.log(this)
},{name:"asd"})
filter()
filter方法:arr.filter((item,index,array) =>{ return 布尔值 },thisArgs)
filter方法就是一个筛选过滤的方法,参数是一个回调函数,回调函数一定会返回一个布尔值,如果保留true保留当前循环的函数,false则去掉
除了第一个参数传回调函数以外,第二个参数可以用于指定改函数运行时的上下文环境,即可以修改函数的this指向,指向第二个参数
var arr = [1, 2, 3, 4, 5]
var i = arr.filter((item, index, array) => {
item *= 10
return false
})
console.log("🚀 ~ i ~ i:", i)
console.log("🚀 ~ arr:", arr)
arr.filter((item, index, array) => {
console.log(this)
},{name:"asd"})
every()
every方法:arr.every((item,index,array) =>{ return 布尔值 },thisArgs)
every方法是一个循环数组的方法,该方法有一个参数是一个回调函数,该回调函数一定要返回布尔值,every方法返回的也是一个布尔值
这个布尔值取决于每一个回调函数内部返回的值,如果每一个回调函数返回的都是true,那么every则返回true
除了第一个参数传回调函数以外,第二个参数可以用于指定改函数运行时的上下文环境,即可以修改函数的this指向,指向第二个参数
代码展示:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var i = arr.every((item, index, array) => {
console.log(item);
return item > 1
})
console.log("🚀 ~ i ~ i:", i)
arr.every((item, index, array) => {
console.log(this)
},{name:"asd"})
some()
some方法是一个循环数组的方法,该方法有一个参数是一个回调函数,该回调函数一定要返回布尔值,some方法
返回也是一个布尔值,有一个是true那么则返回true,全为假才为假
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var i = arr.some((item, index, array) => {
console.log(item);
return item > 7
})
console.log("🚀 ~ i ~ i:", i)
arr.every((item, index, array) => {
console.log(this)
},{name:"asd"})
reduce()
reduce方法是一个数组的迭代方法,该方法是对一个数组里的每一个元素进行迭代,并把当前循环的迭代结果
作为下一次迭代的初始值
reduce方法是数组里面最强大的方法,可以实现其他的任何方法
arr.reduce((上一次迭代的返回值,当前迭代项,当前迭代项的索引,原数组) => {},第一次迭代的初始值)
计算数组总和
const arr = [1, 2, 3, 4, 5];
const sum = arr.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 输出 15
将数组转换为对象
const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
const nameCount = names.reduce((acc, name) => {
acc[name] = (acc[name] || 0) + 1;
return acc;
}, {});
console.log(nameCount); // 输出 { Alice: 2, Bob: 1, Tiff: 1, Bruce: 1 }
因为reduce是JavaScript中用于数组迭代的高阶函数之一,也是我认为最大的数组方法,下面说明一些语法
语法:array.reduce((accumulator, currentValue, currentIndex, array) => {}, initialValue)
- accumulator: 累加器,累积回调函数的返回值。它在每次回调时都会被保留并传递给下一次调用。
- currentValue: 数组中正在处理的元素。
- currentIndex (可选): 数组中当前正在处理的元素的索引。
- array (可选): 调用的数组。
- initialValue (可选):作为第一次调用回调函数时的第一个参数的值。如果没有提供初始值,则将使用数组的第一个元素作为初始累加器的值,并从数组的第二个元素开始迭代。
工作原理:reduce方法通过遍历数组中的每个元素,执行回调函数来累加或者转换数组中的值,并最终返回一个结果。
- 在第一次执行回调函数时,如果提供了initialValue,则accumulator的值为initialValue,currentValue的值为数组的第一个元素。
- 如果没有提供initialValue,则accumulator的值为数组的第一个元素,currentValue的值为数组的第二个元素。
- 回调函数返回的值会成为下一次调用回调函数时的accumulator的值。
- 最后,reduce方法返回的是最后一次调用回调函数后得到的accumulator的值。
下面是我用reduce封装的类似实现其他方法的函数
var myForEach = (array, callback) => {
array.reduce((_, value, item, array) => {
callback(value, item, array);
return undefined;
}, undefined);
};
myForEach([1, 2, 3], (item, index) => {
console.log(item, index);
});
var myMap = (array, callback) => {
return array.reduce((res, value, item, array) => {
res.push(callback(value, item, array))
return res;
}, []);
};
var a = myMap([1, 2, 3], (item, index) => {
console.log(item, index);
return item
});
console.log("🚀 ~ a ~ a:", a)
var myFliter = (array, callback) => {
return array.reduce((res, value, item, array) => {
callback(value, item, array) ? res.push(value) : ""
return res;
}, []);
}
var a = myFliter([1, 2, 3], (item, index) => {
console.log(item, index);
return item > 0
});
console.log("🚀 ~ a ~ a:", a)