js reduce实现中间件_js的reduce实现以及使用场景

本文详细介绍了JavaScript中reduce方法的两种实现方式,并通过多个实际应用场景,如累加、计数器、数组扁平化、斐波那契数列、中间件、对象空值判断、过滤属性、分组、删除指定位置的值、字母游戏和排序等,展示了reduce的灵活性和强大功能。
摘要由CSDN通过智能技术生成

手写实现reduce

实现方式一

Array.prototype.reduce = function (fn, init) {

if (typeof fn !== 'function') {

throw new TypeError('xxx');

}

initArr = this;

arr = initArr.concat();

if (init) arr.unshift(init);

let index, newVal;

while (arr.length > 1) {

index = initArr.length - arr.length + 1;

newVal = fn.call(null, arr[0], arr[1], index, initArr);

arr.splice(0, 2, newVal)

}

return newVal

}

实现方式二 (递归)

const reduceHelper = (fn, acc, idx, array) => {

if (array.length === 0) return acc

const [head, ...tail] = array

idx++

return reduceHelper(fn, fn(acc, head, idx, array), idx, tail)

}

Array.prototype.myReduce = function (cb, initialValue) {

const array = this

const [head, ...tail] = array

const startIndex = initialValue ? -1 : 0

return initialValue ? reduceHelper(cb, initialValue, startIndex, array) : reduceHelper(cb, head, startIndex, tail)

}

应用场景

一: 累加

const sum = arr => arr.reduce((acc, val) => acc + val, 0);

sum([1, 2, 3]);

二: 计数器

let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

let nameNum = names.reduce((pre, cur) => {

if (cur in pre) {

pre[cur]++

} else {

pre[cur] = 1

}

return pre

}, {})

console.log(nameNum); // //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

三: 数组扁平化

const deepFlatten = arr =>

arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []);

console.log(deepFlatten([1, [2, [3, 4, [5, 6]]]]));

四: 生成斐波那契数列

const fibonacci = n => Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);

console.log(fibonacci(5));

五: 中间件

redux中经典的compose函数中运用了这种方式, 通过对中间件的重重层叠, 在真正发起action的时候触发函数执行.

const dispatch = action => {

console.log('action', action);

return action;

}

const middleware1 = dispatch => {

return action => {

console.log("middleware1");

const result = dispatch(action);

console.log("after middleware1");

return result;

}

}

const middleware2 = dispatch => {

return action => {

console.log("middleware2");

const result = dispatch(action);

console.log("after middleware2");

return result;

}

}

const middleware3 = dispatch => {

return action => {

console.log("middleware3");

const result = dispatch(action);

console.log("after middleware3");

return result;

}

}

const compose = middlewares => middlewares.reduce((a, b) => {

return function (args) {

return a(b(args))

}

})

const middlewares = [middleware1, middleware2, middleware3];

const afterDispatch = compose(middlewares)(dispatch);

// const afterDispatch = middleware1(middleware2(middleware3(dispatch)));

const testAction = arg => {

return { type: "TEST_ACTION", params: arg };

};

afterDispatch(testAction("1111"));

六: 对象空值判断

let school = {

name: 'Hope middle school',

created: '2001',

classes: [

{

name: '三年二班',

teachers: [

{ name: '张二蛋', age: 26, sex: '男', actor: '班主任' },

{ name: '王小妞', age: 23, sex: '女', actor: '英语老师' }

]

},

{

name: '明星班',

teachers: [

{ name: '欧阳娜娜', age: 29, sex: '女', actor: '班主任' },

{ name: '李易峰', age: 28, sex: '男', actor: '体育老师' },

{ name: '杨幂', age: 111, sex: '女', actor: '艺术老师' }

]

}

]

};

// 常规做法

school.classes &&

school.classes[0] &&

school.classes[0].teachers &&

school.classes[0].teachers[0] &&

school.classes[0].teachers[0].name

// reduce方法

const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o);

get(['classes', 0, 'teachers', 0, 'name'], school); // 张二蛋

七: 过滤属性

根据给出的键值来遍历,比较对象中是否存在相同键值的的值,然后通过逗号表达式把赋值后的对象赋给下一个的初始值

const pick = (obj, arr) =>

arr.reduce(function (acc, curr) {

if (curr in obj) {

acc[curr] = obj[curr]

return acc;

}

}, {});

// 也可以简写成

const pick2 = (obj, arr) =>

arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});

pick({ a: 1, b: '2', c: 3 }, ['a', 'c']);

八: 分组

首先通过map计算出所有的键值,然后再根据建值进行归类

const groupBy = (arr, func) =>

arr.map(typeof func === 'function' ? func : val => val[func])

.reduce((acc, val, i) => {

acc[val] = (acc[val] || []).concat(arr[i]);

return acc;

}, {});

groupBy([6.1, 4.2, 6.3], Math.floor);

groupBy(['one', 'two', 'three'], 'length');

九: 数组删除指定位置的值

首先根据filter函数过滤出数组中符合条件的值,然后使用reduce在原数组中删除符合条件的值,可以得出最后arr的值变成了[1, 3]

const remove = (arr, fn) =>{

return arr.filter(fn).reduce((acc, cur) => {

arr.splice(arr.indexOf(cur), 1);

return acc.concat(cur);

}, []);

}

const arr = [1, 7, 3, 4, 8];

console.log(remove(arr, n => n % 3 == 1))

console.log(arr)

十: 字母游戏

reduce负责筛选出每一次执行的首字母,递归负责对剩下字母的排列组合。

const anagrams = str => {

if (str.length <= 2) {

return str.length === 2 ? [str, str[1] + str[0]] : str;

}

return str.split("").reduce((acc, letter, i) => {

return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));

}, []);

}

anagrams("abc");

十一: 排序

const orderBy = (arr, props, orders) =>

[...arr].sort((a, b) =>

props.reduce((acc, prop, i) => {

if (acc === 0) {

const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];

acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;

}

return acc;

}, 0)

);

const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fly', age: 26 }];

console.log(orderBy(users, ['age'], ['desc']));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值