手写redux方法以及数组reduce方法
reduce能做什么?
1)求和
2)计算价格
3)合并数据
4)redux的compose方法
这篇文章主要内容是什么?
1)介绍reduce的主要作用
2)手写实现reduce方法
0)了解reduce
在了解reduce的好处之前,我们先知道reduce是什么? reduce是数组的一个方法,函数接受的参数有四个,函数上一次的结果,当前的结果,索引,当前执行的数组;在尾巴处也可以加一个初始的值。每一个参数都有很大的用处,运用好的话,可以幻化出各种变化。
let r = [1,2,3].reduce(('上一次返回的值','当前的值','当前索引','执行的数组') => {
},'第一次的初始值')
1)求和
这个函数执行俩次,第一次a = 1,b = 2,。a+b的结果赋予下一次的a 。 第二次a = 3,b = 3。 运算结束,放回总结果。
// 求和
let r = [1, 2, 3].reduce((a, b) => {
return a + b;
})
console.log(r)
// r = 6
2)计算价格
这个是遍历后台传过来的价格和数量,有时候结构是比较复杂的。这里我们看看第一个,这样是不对的。第一次 100*2+100*2 . 将结果赋予a 那下一次执行 , a.price 和 a.number 都找不到了,都为undefined。所以我们需要一个初始值,将所有的结果累加在初始值上。这里我们看看第二个
函数,给a加个初始值0,也就是在reduce的尾巴加个0, 这样每次b的结果累加在a上。那么价格就可以计算出来了。
// 算价格
let k = [{ price: 100, number: 2 }, { price: 100, number: 2 }, { price: 100, number: 2 }, { price: 100, number: 2 }].reduce((a, b) => {
return a.price * a.number + b.price * b.number;
})
console.log(k)
// k = NaN
// 算价格
let k = [{ price: 100, number: 2 }, { price: 100, number: 2 }, { price: 100, number: 2 }, { price: 100, number: 2 }].reduce((a, b) => {
return a + b.price * b.number;
}, 0)
console.log(k)
// k = 800
3)合并数据
这里的是将key和value和为一个对象,遍历key数组,给一个初始值{},往初始值{}赋值。这样做到了合并数据
// 合并多个数据 let keys = ['name', 'age'];
let value = ['王少', '20']; let obj = keys.reduce((a, b, index, curent) => {
a[b] = value[index];
return a;
}, {}); console.log(obj);
// obj = {name:'王少',age:'20'}
4)redux的compose方法
首先先创造3个方法,第一个将俩个字符串拼起来,第二给转化大写,第三个前后加***
function sum(a, b) {
return a + b;
}
function toUpper(str) {
return str.toUpperCase();
}
function add(str) {
return `***${str}***`
}
正常执行三个方法是这样的,一层套着一层,我们现在有俩种方法实现优化,一种是用reduceRight,从右向左边执行。 一种是reduce,从左到右执行。
sum(toUpper(add('111','asd')))
我们先来看reduceRight方法,我们先来看看执行的代码 compose(add,toUpper,sum)('wangshao','666') 这里是执行俩个函数 , 是一个函数套着一个函数 。外层接受函数数组fns,内层接受实参 ‘wangsaho’,‘666’ 。用pop方法取函数数组最后一位赋值给lastFn,lastFn 作为reducRight的初始值
然后开始从右向左遍历。此时的a是初始值,也就是最后一位add函数。b是第二位 ,toUpper函数。所以返回值就是b(a)。下一次a的值即为 toUpper(add()) ,b的值为sum()。这样就实现完成了。
function compose(...fns) {
return function (...args) {
let lastFn = fns.pop();
return fns.reduceRight((a, b) => {
return b(a)
}, lastFn(...args))
}
};
let r = compose(add, toUpper, sum)('wangshao', '666');
然后,我们将上面的函数用箭头函数优化一下,箭头函数可以将return和{}去掉。就简化为下面的代码。效果是一样的。
let compose = (...fns) => (...args) => { let lastFn = fns.pop(); return fns.reduceRight((a, b) => b(a), lastFn(...args)) };
最后我们来看看redcue方法,这个我们往浅的思考,就是第一个函数嵌套第二个函数。将结果再次嵌套第三个函数。首先最外层还是接受函数数组fns,遍历这个数组将结果返回,这里的a,b是和上面一样的。我们返回一个函数,这个函数是内层函数,参数有实参。 第二次a的值即为toUpper(add(..args)) 。
function compose(...fns) {
return fns.reduce((a, b) => {
return (...args) => {
return a(b(...args))
}
})
}
将上面的函数用箭头函数优化一下,这个更加简短了
let compose = (...fns) => fns.reduce((a, b) => (...args) => a(b(...args)));
我们看到的这俩个方法,第一个是一年前redux的compose方法,第二个是现在redux的compose方法
然后我们继续手写reduce方法,这里在数组的原型上添加一个方法reduce 。 接受俩个参数,一个是回调,一个是初始值prev。然后开始遍历,次数是数组的长度,这里我们在原型上可以用this指向调用自身的数组。 首先我们做一个判断,判断初始值是否为空,是的话则callback的参数a为第一位,b为第二位,index = i+1,第四个参数则为数组本身。将返回的值赋给prev,并且让i++; 执行第二次函数,第二次走下面,callback的a是上一次放回的结果prev,b是现在的元素,index是i,第四个参数是数组本身不变。总的结果放回prev。可以看到,我这里想用forEach来实现。但是好像是改变不了遍历次数和索引的。所以最原生还是用for循环吧。
Array.prototype.reduce = function (callback, prev) {
for (let i = 0; i < this.length; i++) {
if (prev == undefined) {
prev = callback(this[i],this[i+1], i + 1, this);
i++;
} else {
prev = callback(prev,this[i], i , this);
}
}
// this.forEach((e, i) => {
// if (prev == undefined) {
// console.log(e,e+1)
// prev = callback(e,e+1, i + 1, this);
// } else {
// prev = callback(prev,e+1 , i+1, this);
// }
// })
return prev;
};
let r = [1, 2, 3].reduce((a, b, index, current) => {
return a + b
})
有什么觉得奇怪的地方,互相讨论,学习。谢谢
手写redux方法以及数组reduce方法的更多相关文章
- JS进阶篇--JS数组reduce()方法详解及高级技巧
基本概念 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被 ...
- 手写 redux 和 react-redux
1.手写 redux redux.js /** * 手写 redux */ export function createStore(reducer) { // 当前状态 let currentStat ...
- 067 01 Android 零基础入门 01 Java基础语法 08 Java方法 05 数组作为方法参数
067 01 Android 零基础入门 01 Java基础语法 08 Java方法 05 数组作为方法参数 本文知识点:数组作为方法参数 说明:因为时间紧张,本人写博客过程中只是对知识点的关键步骤进 ...
- (手写识别) Zinnia库及其实现方法研究
Zinnia库及其实现方法研究 (转) zinnia是一个开源的手写识别库.采用C++实现.具有手写识别,学习以及文字模型数据制作转换等功能. 项目地址 [http://zinnia.sourcefo ...
- es 5 数组reduce方法记忆
reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值. 概念:对数组中的所有元素调用指定的回调函数.该回调函数的返回值为累积结果,并 ...
- 数组reduce方法以及高级技巧
基本概念: reduce()方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终为一个值. reduce为数组中的每一个元素依次执行回调函数.不包括数组中被删除或从未赋值的元素,接受两 ...
- js数组reduce()方法的使用和一些应用场景
reduce()的使用 reduce()方法为归并类方法,最常见的应用场景就是,计算数组中每一项的总和. reduce()方法会遍历数组的每一项,它接收两个参数: 第一个参数是:每次遍历都会调用的函数 ...
- ES6中的数组reduce()方法详解
reduce() 方法对数组中的每个元素执行一个由我们提供的reducer函数(升序执行),将其结果汇总为单个返回值. 1. 语法reduce说明 arr.reduce(callback(accumu ...
- React深入 - 手写redux api
简介: 手写实现redux基础api createStore( )和store相关方法 api回顾: createStore(reducer, [preloadedState], enhancer) ...
随机推荐
- js原型理解
https://www.cnblogs.com/liuhw/p/10646717.html __proto__的默认指向:https://www.jianshu.com/p/686b61c4a43d
- python3多进程爬虫(第一卷)
进程这个东西概念很多人很模糊,而多进程并发爬虫也算是爬虫几大难点,现在我先说下进程的基本使用: 开启一个python文件 函数sayhi就是一个进程而且是主进程 现在呢我想循环输出NAME,n 正常我 ...
- 隐私标签(Privacy.Tag):轻轻一贴,愉快拍照!
用相机去捕捉精彩瞬间,用照片来记录生活足迹,并实时地与朋友们分享当下的心情,似乎已成为我们忙碌生活中最有趣的调味剂.但随着移动设备照相功能的日益完善,以及各大社交平台的不断兴起,很多时候,你是否也会有 ...
- 亚马逊Prime会员的杀价,能说明会员+会越来越便宜吗?
前段时间,京东又坑了!京东调整了物流方案--从原来的购物不满49元只需6元运费,调整到购物不满46元运费15元,运费猛涨了9元!原本京东PLUS会员每月有5张免运费券,但在运费涨价后运费券限制在6元, ...
- 旅游机票类专业名词---PNR
PNR: PNR是旅客订座记录,即Passenger Name Record的缩写,它反映了旅客的航程,航班座位占用的数量,及旅客信息.适用民航订座系统. 一个PNR由以下几项组成: 姓名组NM 航段 ...
- 2018年宜賓美酒文化節浮空投影舞美特效 / 2018 Yibing Wine Festival Visual Effect Projection
客户 Client:五粮液集团 硬件 Hardware:PC,巴可投影机30,000流明*2 Barco projector 30,000 lumen*2 软件 Software:Resolume, ...
- iPhone X价格下跌!用户依旧冷眼相看为哪般?
X价格下跌!用户依旧冷眼相看为哪般?" title="iPhone X价格下跌!用户依旧冷眼相看为哪般?"> 其实对于刚刚过去的2017年手机市场来说,根本没有一款 ...
- Spring Boot框架开发的Java项目在CentOS7上的部署
需求:上级拿来一份Spring Boot框架开发的Java项目代码让我在服务器上运行起来,只说了一句该框架是自带了Tomcat(不用重新安装Tomcat),一份代码下有两个项目(一个管理端项目,一个用 ...
- Seata-一站式分布式事务解决方案
Fescar 2019 年 1 月,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback),和社区一起共建开源分布式事务解决方案. F ...
- Eclipse如何打开Android工程
一.Eclipse如何打开Android工程 1.你可以在file->new->other->android object选择选项:create object from exists ...