参考: (博主:咸虾米_)各种类型的for循环遍历,forEach/map/filter/for…in/for…of/every/some/includes/reduce的详细用法
1. for 和 forEach
性能上的比较:for性能更优
let arrs = [...Array(9999999).keys()]
let total = 0;
let startTime = Date.now();
// for:
// 支持break跳出整个循环
// 支持continue跳出当前,继续余下循环操作
for(let i=0; i<arrs.length; i++) {
total+=i;
}
let endTime = Date.now();
let countTime = endTime - startTime;
console.log("for:计数---->"+total); // for:计数---->49999985000001
console.log("for:消耗时间---->"+countTime); // 129
total = 0;
startTime = Date.now();
// forEach:
// 不支持break和continue
// 支持return结束当前,继续余下循环操作
arrs.forEach(item=>{
total+=item;
})
endTime = Date.now();
countTime = endTime - startTime;
console.log("forEach:计数---->"+total); // forEach:计数---->49999985000001
console.log("forEach:消耗时间---->"+countTime); // forEach:消耗时间---->267
- for循环直接操作索引,没有额外的函数调用和上下文,所以性能是最快的
- for可以使用break终止,forEach不支持跳出循环
- forEach可以使用return,满足条件使用return可以结束当前这次循环,但是剩下的循环还是继续跑完,但有forEach内加不加return其实消耗的时间都是差不多相同的
异步同步化的支持度:for支持,forEach不支持
async function fetchData_for() {
let arrs = [1, 2, 3];
let datas = [];
// for:支持异步等待
for (let i = 0; i < arrs.length; i++) {
const { data } = await getData({
url:"http://jsonplaceholder.typicode.com/posts/" + arrs[i]
});
datas.push(data);
}
console.log(datas); // (3) [{…}, {…}, {…}]
}
fetchData_for();
function fetchData_forEach() {
let arrs = [1, 2, 3];
let datas = [];
// forEach:不支持异步等待
arrs.forEach(async item=>{
const { data } = await getData({
url:"http://jsonplaceholder.typicode.com/posts/" + item
})
datas.push(data)
})
console.log(datas); // []
}
fetchData_forEach();
2. map
map()
方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
用法1:将数组内每个元素×2后,获取新数组
let arrs = [1,2,3,4];
let newArrs = arrs.map((element, index, array) => {
// 参数1 element:数组中当前正在处理的元素。
// 参数2 index:正在处理的元素在数组中的索引。
// 参数3 array:调用了 map() 的数组本身。
return element * 2;
});
console.log(newArrs); // [2, 4, 6, 8]
用法2:将数组对象内每个元素的名称拿出来,作为一个新数组
let peopleList = [
{
name: '张三',
age: 18,
},
{
name: '李四',
age: 19,
},
{
name: '王五',
age: 20,
},
];
let names = peopleList.map(item => item.name);
console.log(names); // ['张三', '李四', '王五']
用法3:修改元数组对象,生成新数组
let peopleList = [
{
name: '张三',
age: 18,
},
{
name: '李四',
age: 19,
},
{
name: '王五',
age: 20,
},
];
let newPeopleList = peopleList.map(item => {
return {
...item,
age: item.age + '岁',
intro: '我的名字叫' + item.name,
}
})
// let newPeopleList = peopleList.map(item=>({...item, age: item.age + "岁", intro: '我的名字叫' + item.name})); // 一行简写
console.log(newPeopleList);
// [
// {
// "name": "张三",
// "age": "18岁",
// "intro": "我的名字叫张三"
// },
// {
// "name": "李四",
// "age": "19岁",
// "intro": "我的名字叫李四"
// },
// {
// "name": "王五",
// "age": "20岁",
// "intro": "我的名字叫王五"
// }
// ]
用法4:将原数组中属性进行更换,配合对象解构,可以更直观
let arr = [{key:0,content:"篮球"},{key:1,content:"足球"},{key:2,content:"排球"}];
let newArr = arr.map(({key,content})=>({value:key,text:content}));
console.log(newArr); // [{value: 0, text: '篮球'},{value: 1, text: '足球'},{value: 2, text: '排球'}]
用法5:将异步请求map到新数组中,使用Promise.all同事处理多个Promise
let arr = [1, 2, 3];
const promises = arr.map(async (num) => {
const result = await getData({
url:"http://jsonplaceholder.typicode.com/posts/" + num
})
return result;
});
console.log(promises); // [Promise, Promise, Promise]
Promise.all(promises).then(res => {
console.log(res); // (3) [{…}, {…}, {…}]
})
3. filter
filter()
方法创建给定数组一部分的浅拷贝,其包含通过所提供函数实现的测试的所有元素。filter()过滤方法,会对原数组中的每个元素应用指定的函数,并返回一个新数组,其中包含符合条件的元素。原数组不会受到影响。
用法1:过滤出数值数组中的偶数
let arrs = [5,7,8,15,22,1,2];
let newArrs = arrs.filter((item, index, array) => {
// 参数1:数组中当前正在处理的元素。
// 参数2:正在处理的元素在数组中的索引。
// 参数3: 调用了 filter() 的数组本身
console.log(item, index, array);
return item % 2 === 0;
})
console.log(newArrs); // [8, 22, 2]
用法2:数组去重,结合indexOf方法
let arrs = [6,1,2,3,5,3,6];
let newArrs = arrs.filter((item,index,self)=>{
return self.indexOf(item) === index
})
console.log(newArrs); // [6, 1, 2, 3, 5]
用法3:数组对象中过滤掉无用数据
let arrs = [{id:1,name:"HTML5"},{id:2,name:"JavaScript"},{id:null,name:"小程序"},{name:"NodeJS"},{id:3,name:"VueJS"}];
let newArrs = arrs.filter(item=>{
return item.id
})
console.log(newArrs); // [{id:1,name:"HTML5"},{id:2,name:"JavaScript"},{id:3,name:"VueJS"}]
用法4:filter和map用链式写法组合使用
let arrs = ['6','1','2','3','5','3','6'];
let newArrs = arrs.filter((item,index,self) => {
return self.indexOf(item) === index
}).map(Number) // 字符串转数值型
console.log(newArrs); // [6, 1, 2, 3, 5]
4. reduce
reduce()
方法对数组中的每个元素按序执行一个提供的 reduce 函数,每一次运行 reduce 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
用法1:求和/求积
let arr = [1, 2, 3, 4];
let result = arr.reduce((prev, current, index, array) => {
// 参数1:上一次调用callbackFn的结果(必须)
// 参数2:当前元素的值(必须)
// 参数3:currentValue在数组中的索引
// 参数4:调用了reduce()的数组本身
return prev + current;
}, 0) // 这里的0为初始值 当有初始值时,循环从arr[0]开始,第一个循环的prev即为该初始值
// 当没有初始值参数时,循环从arr[1]开始,第一个循环的prev及为a[0]
// 当不知道数组内是不有值时,进行reduce操作最好加上初始值参数,防止程序报错
console.log(result); // 10
let result2 = arr.reduce((prev, current, index, array) =>{
return prev * current;
})
console.log(result2); // 24
用法2:求最大值/最小值
let arrs = [5, 6, 1, 22, 3, 7];
let result = arrs.reduce((prev, current, index) => {
return Math.max(prev, current);
}, 0)
console.log(result); // 22
let result2 = arrs.reduce((prev, current, index) => {
return Math.min(prev, current);
}, 0)
console.log(result2); // 0
用法3:对数组对象处理
let arrs = [{ name: "张三", age: 29 }, { name: "李四", age: 16 }, { name: "王五", age: 50 }, { name: "小明", age: 21 }];
let result = arrs.reduce((prev, current, index) => {
return prev + current.age
}, 0)
console.log(result); // 116
5. every
every()
方法测试一个数组内的所有元素是否都能通过指定函数的测试。它返回一个布尔值,全部满足返回true,只要有一项不满足则返回false。
用法1:检查数组中的所有元素是否满足特定条件
let arr1 = [2, 4, 6, 8];
let arr2 = [1, 2, 4, 6, 8];
let result1 = arr1.every((item, index, array) => {
// 参数1:数组中当前正在处理的元素。
// 参数2:正在处理的元素在数组中的索引。
// 参数3:调用了 every() 的数组本身。
console.log(item, index, array);
return item % 2 === 0;
});
let result2 = arr2.every(item => item % 2 === 0);
console.log(result1); // true
console.log(result2); // false
用法2:检查数组对象中的某个属性是否都满足条件
let arrs = [{ name: "华为", price: 5899, stock: true }, { name: "苹果", price: 9999, stock: false }, { name: "小米", price: 4399, stock: true }, { name: "红米", price: 899, stock: true }];
let result = arrs.every(item => item.stock);
console.log(result); // false
用法3:检测对象内所有属性是否都有值,配合Object.values()(用于检查表单是否都填写)
let obj1 = {
name: 'name',
title: 'title',
}
let obj2 = {
name: 'name',
title: '',
}
let result1 = Object.values(obj1).every(item => item);
let result2 = Object.values(obj2).every(item => item);
console.log(result1, result2); // true false
6. some
some()
方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true,则返回 true;否则返回 false。它不会修改数组。只要找到满足的就不再往下遍历
用法1:检查数组中的是否有满足特定条件的元素
let arrs = [55, 26, 3, 12, 39];
let result = arrs.some((item, index, array) => {
// 参数1:数组中当前正在处理的元素。
// 参数2:正在处理的元素在数组中的索引。
// 参数3:调用了 some() 的数组本身。
console.log(item, index, array);
// 找到满足条件就不再往下遍历
// 55 0 [55, 26, 3, 12, 39]
// 26 1 [55, 26, 3, 12, 39]
return item % 2 === 0;
});
console.log(result); // true
用法2:检查数组对象中的是否有满足特定条件的元素
let arrs = [{ name: "华为", price: 5899, stock: true }, { name: "苹果", price: 9999, stock: false }, { name: "小米", price: 4399, stock: true }, { name: "红米", price: 899, stock: true }];
let result = arrs.some(item => item.price < 1000 && item.stock);
console.log(result); // true
用法3:检测对象内是否存在有值的属性,配合Object.values()(用于检查表单)
let obj1 = {
name: '',
title: 'title',
}
let obj2 = {
name: '',
title: '',
}
let result1 = Object.values(obj1).some(item => item);
let result2 = Object.values(obj2).some(item => item);
console.log(result1, result2); // true false
some 和 evey 的对比
some()
只要有一个遍历项满足条件就返回trueevey()
要所有遍历项都满足条件才返回true
7. includes
includes()
方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
用法1:基础用法,检查数组中是否含有指定值
// 参数1:需要查找的值。
// 参数2:开始搜索的索引(从零开始),会转换为整数。
let arr = [1, 2, 3, 4, 5];
console.log(arr.includes(2)); // true
console.log(arr.includes(2, 2)); // false
用法2:every和includes配合,检测一个数组是否包含另一个数组
let arrs1 = [1, 2, 3, 4, 5, 6, 7];
let arrs2 = [1, 2, 3];
let arrs3 = [0, 2, 3];
let result1 = arrs2.every(item => arrs1.includes(item));
let result2 = arrs3.every(item => arrs1.includes(item));
console.log(result1, result2); // true false
8. find
find()
方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。只要找到满足的就不再往下遍历。
用法1:找到数值中满足条件的第一个元素
let arrs = [55, 26, 3, 12, 39];
let result = arrs.find((item, index, array) => {
// 参数1:数组中当前正在处理的元素。
// 参数2:正在处理的元素在数组中的索引。
// 参数3:调用了 find() 的数组本身。
console.log(item, index, array);
// 找到满足条件就不再往下遍历
// 55 0 [55, 26, 3, 12, 39]
// 26 1 [55, 26, 3, 12, 39]
return item % 2 === 0;
});
console.log(result); // 26
用法2:找到数组对象中的满足特定条件的第一个元素
let arrs = [{ name: "华为", price: 5899, stock: true }, { name: "苹果", price: 9999, stock: false }, { name: "小米", price: 4399, stock: true }, { name: "红米", price: 899, stock: true }];
let result = arrs.find(item => item.price < 1000 && item.stock);
console.log(result); // {name: '红米', price: 899, stock: true}
find 和 some的对比
返回值不同:
- find返回找到的满足条件的数组元素
- some返回布尔值,表示是否存在满足条件的数组元素