数组的reduce方法和compose组合函数

版权声明:本文为博主原创文章,未经博主允许不得转载。原账号CreabineChen现已不用,所有博客均已迁移过来。 https://blog.csdn.net/Creabine/article/details/87724215

前两天在群里看到一道题,折腾半天没做出来。今天查了查,了解了前因后果,在此整理记录一下。

参考资料:

题目:

const fn1 = x => x+1;
const fn2 = x => x+2;
const fn3 = x => x+3;
const fn4 = x => x+4;

let Fn = compose(fn1, fn2, fn3, fn4);
console.log(Fn(0)); // 10
console.log(Fn(5)); // 15
// 求compose函数

数组的reduce方法

数组的reduce方法相比其他的方法要复杂一些,但理解之后也不难,用法如下:

array.reduce((accumulator, item, index, array) => {
	// do something...
}, initialValue)

reduce方法能够对数组使用,他接受两个参数,第一个参数是个函数fn,第二个参数initialValue为可选参数,表示累加器的初始值。

fn中有4个参数,其参数的值会被initialValue存在与否所影响:

  • initialValue存在

参数为:

  1. accumulator: 累加器,初始值为initialValue的值
  2. item:数组的当前项,从第0项开始
  3. index:数组的当前项对应的下标,从0开始
  4. array:数组本身
  • 而当initialValue不存在

参数为:

  1. accumulator: 累加器,初始值为数组第0项
  2. item:数组的当前项,因为 accumulator为第0项,所以这里从1开始
  3. index:数组的当前项对应的下标,从1开始
  4. array:数组本身

简单的用例:

// 
[0, 1, 2, 3, 4].reduce(function(accumulator, item){
  return accumulator + item;
});

compose函数

compose是redux源码中使用过的方法。他是函数式编程里常用的组合函数,和 redux 本身没有什么多大关系,先了解下函数式编程的一些概念:

纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。 代码组合

代码:

export default function compose(...funcs) {
	if (funcs.length === 0) {
		return arg => arg
	}
	
	if (funcs.length === 1) {
		return funcs[0]
	}
	// 这里注意,因为reduce没有传入第二个参数initValue
	// 此时a的初始值为第0项, b为第1项
	return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

其实 compose 函数做的事就是把 var a = fn1(fn2(fn3(fn4(x)))) 这种嵌套的调用方式改成 var a = compose(fn1,fn2,fn3,fn4)(x) 的方式调用。

举一个实际的例子,看看这个函数是怎么执行的:

const fn1 = x => x+1;
const fn2 = x => x+2;
const fn3 = x => x+3;
const fn4 = x => x+4;

let x = 0

// 假设我这里想求得这样的值
let a = fn1(fn2(fn3(fn4(x)))) // 0 + 4 + 3 + 2 + 1 = 10
// 根据compose的功能,我们可以把上面的这条式子改成如下:
let composeFn = compose(fn1, fn2, fn3, fn4)
let b = composeFn(x) // 理论上也应该得到10

看一下compose(fn1, fn2, fn3, fn4)根据 compose 的源码, 其实执行的就是: [fn1,fn2,fn3.fn4].reduce((a, b) => (...args) => a(b(...args)))

第几轮循环 a的值 b的值 返回的值
第一轮循环 fn1 fn2 (…args) => fn1(fn2(…args))
第二轮循环 (…args) => fn1(fn2(…args)) fn3 (…args) => fn1(fn2(fn3(…args)))
第三轮循环 (…args) => fn1(fn2(fn3(…args))) fn4 (…args) => fn1(fn2(fn3(fn4(…args))))

循环最后的返回值就是 (...args) => fn1(fn2(fn3(fn4(...args))))。所以经过 compose 处理过之后,函数就变成我们想要的格式了。

猜你喜欢

转载自blog.csdn.net/Creabine/article/details/87724215