浅析curry

109 阅读2分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

概念

将多参数的函数fn,转化成多个传入一个参数的函数,达到某个条件后执行函数fn
偏柯里化: 转化成多个传入一个或多个参数的函数

前言

Arguments对象

是一个对应于传递给函数的参数的类数组对象。--- MDN

是非箭头函数的局部变量,在函数内部使用

情景: 传递可变数量的参数的函数

区别: arguments.length --- 实参的个数 function.length --- 形参的个数

// 行为: 在非严格模式下,arguments会跟踪参数的值,
即修改参数a 的值,会改变arguments[0]的值;修改arguments[0]的值会改变a的值
但是使用了,解构赋值、剩余参数、默认参数会影响此行为
(function (a) {
  a = 1;
  console.log(arguments[0])
})(10)
(function (a) {
  arguments[0] = 1
  console.log(a)
})(9)
转化为数组,可使用数组的方法
Array.prototype.slice.apply(arguments)
[].slice.apply(arguments)

es5
Array.from(arguments)
[...arguments]

正文

原理: 利用了闭包将传入的参数存储起来

image.png

function curry1 (fn) {
  const _argus = []
  const length = fn.length // 条件
  return (function inner(...argus){
    if(args.length !== 0){
      _argus.push(...argus)
    }
    const that = this
    return args.length >= length ? fn.apply(that, _argus) : (...args)=>inner.apply(that,args)
    //或 return args.length >= length ? fn.apply(that, _argus) : inner.bind(that)
  })()
}
function curry2 (fn, ...agrs){
  const that = this
  return args.length >= fn.length ? fn.apply(that, args) : (...argus) => curry.call(that, fn, ...args,...argus)
}
// 不满足条件时,返回一个可传参的可调用的函数

使用场景

fn是多参数的,且参数类型没有很强的区分度

题目

(一)

// 单个单个参数传递
// calculate(1)(2)(3)('+')

function curring1 (fn, ...args) {
  return function (x) {
    const that = this
    // 加号是判断条件
    return x==='+' ? fn.apply(that, args) : curring1.call(that, fn, x, ...args)
  }
}
const calculate1 = curring1(function(...args){
    return args.reduce((acc, cur)=>acc+cur,0)
})

// 执行函数验证 
console.log(calculate1(1)(2)('+')) //--- 3

(二)

// 分批参数传递
// calculate(1,2)(4)(3,'+')

function curring2 (fn) {
  const that = this
  return function inner(...args) {
    const length = args.length;
    if(length !== 0 && args[length-1] == '+'){
      return fn.apply(that, args.slice(0, length-1))
    }
    return (...argus) => inner.call(that,...args, ...argus)
  }
}
const calculate2 = curring2(function(...args){
    return args.reduce((acc, cur)=>acc+cur,0)
})


// 执行函数验证 
console.log(calculate2(1,2)(4)(3,'+')) // --- 10