js 函数 柯里化 的学习

函数柯里化是什么?

接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
分析一下

  • 输入是一个函数,并且这个函数拥有n个参数
  • 输出也是一个函数,并且可以使用fn()()()这种方式调用
  • 参数被柯里化过程中的函数被拆分

通过分析可以得到 (1)需要对函数的参数进行收集(闭包缓存)(2)链式调用

那我们用柯里化来简单实现一个需求

 add(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)() // 133

//简单实现需求

function add(){
	let ags= [...arguments]
	let curry= function (){
		if(arguments.length===0){
			return ags.reduce((a,b)=>a+b)
		}else{
			ags= [..ags,...arguments]
			return curry
		}
	}
	//形成闭包
	return curry
}

上面虽然实现了主要功能,但是代码的质量不是很高!无法进行拓展
我们需要把上面的代码进行单一职责划分(1)参数收集(2)逻辑部分(相加)

function curry () {
  let ags = [...arguments]
  let currying = function () {
    if (arguments.length === 0) {
      return ags
    } else {
      ags = [...ags, ...arguments]
      return currying
    }
  }
  //形成闭包
  return currying
}
function add (data) {
  return data.reduce((a, b) => a + b)
}
add(curry(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)()) //133

或者

function curry (fn,...data) {
	//参数传递的时候 缓存除了第一个参数的函数之外的所有参数
  let ags = [...data]
  // let args = [].slice.call(arguments, 1);
  //[].slice.call(arguments, 1)等同于arguments.slice(1)
  //[].slice.call 的原因是 arguments是个类数组 并不具备array原型上的方法
  //直接使用 arguments.slice(1)无法使用
  let currying = function () {
    if (arguments.length === 0) {
      return fn.apply(this,ags)
    } else {
      ags = [...ags, ...arguments]
      return currying
    }
  }
  //形成闭包
  return currying
}
function add () {
  return [].reduce.call(arguments,(a, b) => a + b)
}
curry(add,2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)()  //133

整体看上去还是不够简洁 接着简化

function curry(fn,data=[]){
	return ( ...args )=>{ //args 为curry的 第二个参数 是每一项的数据
		//自执行函数 前面函数会接收后面传递的参数
		//a为拼接的累加数据  b为 ...args 每一次调用的形参数据
		//链式调用当前形参的长度为0时 结束递归循环 并返回调用函数把所有收集的参数传递给执行参数
		return ((a,b)=> b.length === 0?fn(...ages): curry(fn,a))([...data,...args],...args)
	}
}
let adds = curry((...x) => x.reduce((a, b) => a + b))
console.log(adds(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98)())  //133
////遇到参数个数为0的情况才执行
console.log(adds(2)(1, 3, 4)(2, 3)(3)(4, 6)(7, 98))  //函数

上面看出来 柯里化的作用之一是收集数据 参数复用;利用闭包的特性,将所有参数都搜集到之后再一并执行。

function curry(fn, ...args) {
    return function(...innerArgs) {
        const allArgs = [...args, ...innerArgs];
        if (fn.length <= allArgs.length) {
            // 说明已经接受完所有参数,这个时候可以执行了
            return fn.apply(this, allArgs);
        } else {
            // 继续返回函数,收集参数
            return curry(fn, ...allArgs);
        }
    }
}
function curry(fn, ...args) {
    return function(...innerArgs) {
        const allArgs = [...args, ...innerArgs];
        if (fn.length <= allArgs.length) {
            // 说明已经接受完所有参数,这个时候可以执行了
            return fn.apply(this, allArgs);
        } else {
            // 继续返回函数,收集参数
            return curry(fn, ...allArgs);
        }
    }
}
const amount = [
    { deposit: 120, finalPayment: 200 },
    { deposit: 110, finalPayment: 300 },
    { deposit: 130, finalPayment: 100 },
];
const sort = curry(function(field, a, b) {
    return a[field] - b[field];
})
console.log(amount.slice().sort(sort('deposit'))); // deposit进行排序
console.log(amount.slice().sort(sort('finalPayment'))); // finalPayment进行排序
posted @ 2022-01-17 16:31  xiao旭  阅读(38)  评论(0编辑  收藏  举报