实现reduce compose bind call apply
1.实现Reduce
«««< HEAD ======= Reduce 的第一个参数是核心,它对数组的每一项进行”叠加操作“ 然后最后返回一个值,作为reduce方法的返回值。callback包含以下4个参数。
- previousValue 表示 callback函数上一次的返回值
- currentValue表示 数组遍历中正在处理的元素。
- currentIndex表示可选参数,表示currentValue在数组中对应的索引,如果提供了initialValue则起始索引值为0,否则为1。
- array是可选参数,表示调用reduce方法的数组。
下面我来展示一个顺序调用promise的代码:
const runPromiseInSequence = (array, vlaue) => array.reduce(
(promiseChain,currentFunction) => promiseChain.then(currentFunction),
Promise.resolve(value)
)
const f1 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("p1 is running!")
resolve()
},1000)
})
}
const f2 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("p2 is running!")
resolve()
},1000)
})
}
runPromiseInSequence([f1(),f2()],"init")
手写实现一个reduce:
Array.prototype.myreduce = function(func, initialValue){
let arr = this
let base = typeof initialValue === "undefined" ? arr[0] : arr[1]
let startPoint = typeof initialValue === "undefined" ? 1 : 0
arr.slice(startPoint).forEach(function(var, index)=>{
base = func(base, val, index + startPoint, arr)
})
return base
}
2.compose方法
Compose 方法主要目的就是为了执行一连串的不定长度的任务。
let funcs = [fn1,fn2,fn3,fn4]
let composeFunc = compose(funcs)
composeFunc(args)
=======> 相当于
fn1(fn2(fn3(fn4(args))))
下面来实现一下compose
const compose = (...funcs)=>{
let init = funcs.pop()
return (...args)=>{
funcs.reverse().reduce((result,func)=>{
chain.then(result => func.apply(null,result))
},Promise.resolve(init.apply(null,args)))
}
}
下面展示一下redux中compose写法:
function compose(...funcs){
if(funcs.length === 0){
return args => args
}
if(funcs.length === 1){
return. funcs[0]
}
return funcs.reduce((a,b)=>(...args)=> a(b(...args)))
// 这个实现真的是非常的巧妙
}
3.apply 和 bind 的实现
我先来写一下之前我自己实现的bind哈
Function.protoType.mybind = function(context,...args1){
let func = this
return function(...args2){
return func.apply(context,[...args1,...args2])
}
}
这个bind实现似乎已经还算可以了,但是实际上还是有一定的问题的,原因呢,就是我们在前面this的指向问题的时候,说到就是bind之后的函数配合new使用的时候,会忽略掉原来绑定的this,按照正常的new走向去进行。所以下面我们来实现新的bind函数。
Function.prototype.mybind = function(context,...args1){
let func = this
return function(...args2){
return func.apply(this instanceof func ? this : context,[...args1,...args2])
}
}
apply和call的实现就比较简单了
Function.prototype.mycall = function(targetObject,...argsArray){
if(typeof targetObject === "undefined" || targetObject === null){
targetObject = window
}
targetObject = new Object(targetObject)
const targetFnKey = "targetFnKey"
targetObject[targetFnKey] = this
const result = targetObject[targetFnKey](...argsArray)
delete targetObject[targetFnKey]
return result
}
Function.prototype.mycall = function(targetObject,argsArray){
if(typeof argsArray === "undefined" || argsArray === null){
argsArray = []
}
if(typeof targetObject === "undefined" || targetObject === null){
targetObject = window
}
targetObject = new Object(targetObject)
const targetFnKey = "targetFnKey"
targetObject[targetFnKey] = this
const result = targetObject[targetFnKey](...argsArray)
delete targetObject[targetFnKey]
return result
}
4db3b043ec229eeeb6ea0fcafb33f19eaf3fb0b9