函数柯理化
有时候会遇到相似于这种需要
add(5)(2)(3)=10
add(2,5)(3)=10
add(1)(7,2)=10
add(1)(8)(1)()=10
add(7,1)(1)(1)()=10
add(4)(2,1)(1)(2)()=10
柯理化的两种写法
一、传入的参数个数满足函数执行的参数个数,即开始执行函数
function curry_(fn) { // 返回一个新函数judge,接管参数为 ...args return function judge(...arg) { if (arg.length >= fn.length) { //新函数接管的参数长度是否满足函数执行须要接管的长度 return fn(...arg) // 满足要求,执行 fn 函数,传入新函数的参数 } else { // 不满足要求,递归 judge 函数 整合下一个执行所传递的参数 return function(...args) { return judge(...args, ...arg) } } }}var curry_fn = curry_(function(a, b, c) { return a + b + c});console.log(curry_fn(5)(2)(3), '无限参数柯理化');//10es6简化: const curry_ = fn =>judge = (...args) =>args.length === fn.length ?fn(...args) : (...arg) => judge(...args, ...arg)
二、传入的参数最初一个拿到的参数值为空,即开始执行函数
function curry_(fn) { return function judge(...arg) { //返回新函数,此时arg为[23, 1],即curry_fn传入的第一个参数 return function(...args) { //返回每次执行前一个函数之后的函数即curry_fn(23, 1)执行之后的函数,args为3、4、0 if (!args.length) { //如果后一个函数没有参数即为(),则开始执行函数 return fn(...arg) } else { //如果后一个函数的参数存在,则进行递归,存入arg中 return judge(...args, ...arg); } } }}var curry_fn = curry_(function(...args) { return args.reduce((a, b) => a + b, 0)});console.log(curry_fn(2, 1)(3)(4)(), '无限参数柯理化');//10es6简化: const adder_ = fn => judge = (...arg) => (...args) => !args.length ? fn(...arg) : judge(...arg, ...args)
compose函数
1、从右向左以此执行
2、且上一个函数的执行后果作为下一个函数的参数
3、第一个函数是多参数,前面的函数都是一个参数
4、所有函数的执行都是同步的
let greeting = (...arg) => 'hello, ' + arg.join(' ')//第一个函数(多参数)let toUpper = str => str.toUpperCase()//第二个函数let timing = str => `${str} time= ${+new Date()}`//第三个函数//办法一、reduce法let compose = function(...func) { //如果没有函数,则返回compose_my函数中第一个参数 if (func.length == 0) { return function(arg) { return arg } } //如果只有一个函数,则返回返回这个函数 if (func.length == 1) { return func[0] } //返回reduce解决的后果 return func.reduce((itemFn, callback) => { //初始callback为第一个函数即 greeting() return function(...arg) { //arg为承受处理函数返回的最终函数的参数 即'jack', 'smith', 'wang' return itemFn(callback(...arg)) //第一个函数承受多个参数,返回一个值被下一个函数作为参数,最终输入 } })}//es6版: let compose = (...funcs) => { if (funcs.length === 0) return arg => arg if (funcs.length === 1) return funcs[0] return funcs.reduce((a, b) => (...args) => a(b(...args))) }//办法二、滑块递归法let compose = (...args) => { var len = args.length // 记录咱们传入所有函数的个数 var count = len - 1 // 游标记录函数执行状况, 也作为咱们运行中函数的索引 var result // 后果, 每次函数执行实现后, 向下传递 return function f1(...arg) { //arg为承受处理函数返回的最终函数的参数 即'jack', 'smith', 'wang' result = args[count](...arg) if (count <= 0) { //只有一个函数时 count = len - 1 return result } else { //多个函数时,游标挪动,递归执行 count-- return f1(result) } }}let fn = compose(timing, toUpper, greeting)console.log(fn('jack', 'smith', 'wang'))