JavaScript中循环数组除了有for循环
、forEach
、map
、filter
、every
、some
等外还有一个非常好用的reduce
。
reduce
会循环数组中的每一项,在循环过程中我们可以对根据需要对任意一项进行处理,并返回处理后的数据,循环结束后reduce
会将之前返回的数据进行汇总,最终我们只得到一个结果。有点类似于map
方法,但map
只能返回一个数组,而reduce
可以返回任意类型的数据
reduce
用法:
// 没有初始值
let res = arr.reduce((res, item, index, arr) => {
...
});
/* 传递一个初始值。传递的初始值的数据类型是什么,reduce最后得到的结果的数据类型就是什么
此处 res2 变量的结果是一个对象
*/
let res2 = arr.reduce((res, item, index, arr) => {
...
}, {});
1、计算数组中所有数字的和
let arr = [10,55.9,21,0.1,3,8];
let res = arr.reduce((res, item) => {
// 由于没有给初始值,第一次循环的时候 res 为undefined
let sum = (typeof res === 'undefined') ? (0 + item) : res + item;
// 这里一定要将结果return出去,否则后面的循环中res就为undefined了
return sum;
});
console.log('res', res); // 输出结果为:98
2、计算总分数
这题与第1题基本上是相似的,但在实际工作中这题的情况比较多
let arr = [
{subject: '语文', score: 90},
{subject: '数学', score: 80},
{subject: '英语', score: 78}
];
// 这里一定要给个初始值,否则res为当前循环项
let res = arr.reduce((res, item) => {
let score = item.score;
let sum = res + score;
return sum;
}, 0);
console.log(res); // 248
3、统计数组中重复字母出现的次数
let arr = ['a','e','b','a','c','d','d','e'];
let res = arr.reduce((res, item) => {
// 由于传递了初始值,所以第1次循环的时候res就是一个object,不会为undefined
if(item in res){
res[item] = res[item] + 1;
}else{
res[item] = 1;
}
/*
{
a: 2,
e: 2,
b: 1,
c: 1,
d: 2
}
*/
return res;
}, {});
console.log(res);
4、多个异步变同步执行(2020-06-19)
在ES6时代我们可以很方便的使用promise
,在不使用Promise.all
的情况下如何使多个promise
同步执行呢?
比如我们有3个接口,A、B、C,它们的依赖关系是C->B->A
,在不使用Promise.all
的情况下如何才能达到Promise.all
的效果?
请看下面代码
// 获取产品列表
function getProductList() {
return new Promise(resolve => {
setTimeout(() => {
console.log('getProductList');
let productList = [
{id: '1', name: '华为P30'},
{id: '2', name: '华为P30 Pro'}
];
resolve(productList[0].id);
}, 1000);
});
}
// 根据产品id获取产品详情
function getProductInfo(pid) {
return new Promise(resolve => {
setTimeout(() => {
console.log('getProductInfo', pid);
let product = {
id: '1',
name: '华为P30',
price: 3500,
cid: 'c_1'
};
resolve(product.cid);
}, 700);
});
}
// 获取产品的父分类
function getProductParentCategory(cid) {
return new Promise(resolve => {
setTimeout(() => {
console.log('getProductParentCategory', cid);
resolve({
id: 'c_1',
cname: '高端手机'
});
}, 300);
});
}
/**
* 组合promise
* @param promises
* @returns {function(...[*]=)}
*/
function composePromise(...promises) {
let res = function() {
return promises.reduce((res, item) => {
return res.then(item);
}, Promise.resolve());
}
return res();
}
composePromise(getProductList, getProductInfo, getProductParentCategory)
.then(res => {
console.log('三个promise执行结束了');
console.log('父分类',res);
})
.catch(err => {
console.error(err);
});
5、扁平化数组-任意深度(2020-07-29)
let arr = [1, [2, {name: '张三'}, 3, [4, 5, [6, 7, [8,9]]]]];
这样的一个未知深度的多维数组要求转成一维数组你会怎么做?
如果可以使用ES6
那么我们可以使用ES的flat()
函数来解决,arr.flat(Infinity)
只需要这么一行代码就搞定了,但如果不允许使用的话我们也可以有多种解决方式,其中就可以使用reduce()
函数
废话不多说,直接上代码
let arr = [1, [2, {name: '张三'}, 3, [4, 5, [6, 7, [8,9]]]]];
// 扁平化数组
function flat(arr){
return arr.reduce(function (res, item){
if(({}).toString.call(item) === '[object Array]'){
([]).push.apply(res, flat(item));
}else{
res.push(item);
}
return res;
}, []);
};
// [1,2,{"name":"张三"},3,4,5,6,7,8,9]
console.log(flat(arr));
// [1,2,{"name":"张三"},3,4,5,6,7,8,9]
console.log(arr.flat(Infinity));
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。