前端如何实现 柯里化(curry)

176 阅读2分钟

@author: 郭瑞峰 @createTime: 2023/05/20 @updateTime: 2023/05/24

初窥门径

下面是一个题

// 定义一个函数resetAdd,让其所有值相加
const add = (a, b, c) => (a + b + c)

console.log(resetAdd(2, 4, 6)) // 12
console.log(resetAdd(2, 4)(6)) // 12
console.log(resetAdd(2)(4, 6)) // 12
console.log(resetAdd(2)(4)(6)) // 12

先想想看吧

想好了么?

咱再想想看

分析

共同:都是传三个参数 区别:传入顺序不一样

省略其他的,直接进入主题: 柯里化(curry)

柯里化(curry)

简单解释:函数传值传进去,传够了就运行,传不够就返回函数继续传,直到传够为止

详细解释:

在计算机科学中,柯里化(Currying)是把接受多个参数的
函数变换成接受一个单一参数(最初函数的第一个参数)的函
数,并且返回接受余下的参数且返回结果的新函数的技术。
这个技术由 Christopher Strachey 以逻辑学家Haskell
Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob
Frege 发明的。

柯里化函数实例

const curry = (fn) => {
  const curried = (...args) => {
    if (args.length >= fn.length) {
	// 传参数量够,直接执行
      return fn.apply(this, args)
    } else {
	// 传参数量不够,返回函数继续传递函数
      return (...args2) => curried.apply(this, args.concat(args2))
    }
  }
  return curried
}

柯里化就是这么简单,所以说方才的题写法就应该是这样

const add = (a, b, c) => (a + b + c)

const curry = (fn) => {
  const curried = (...args) => {
    if (args.length >= fn.length) {
      return fn.apply(this, args)
    } else {
      return (...args2) => curried.apply(this, args.concat(args2))
    }
  }
  return curried
}

const resetAdd = curry(add)

console.log(resetAdd(2, 4, 6)) // 12
console.log(resetAdd(2, 4)(6)) // 12
console.log(resetAdd(2)(4, 6)) // 12
console.log(resetAdd(2)(4)(6)) // 12

补充

函数的apply, call, bind

apply

Function.apply方法调用时,将this指针指向方法第一个参数,后续传参以数组形式传递,直接执行

const add = (a, b) => {
  return a + b + this.c
}

const obj = { c: 3 }
// Function.apply(newThis, [...args])
console.log(add.apply(obj, [1, 2]))
// 6

call

Function.call方法调用时,将this指针指向方法第一个参数,后续传参直接传,直接执行

const add = (a, b) => {
  return a + b + this.c
}

const obj = { c: 3 }
// Function.call(newThis, ...args)
console.log(add.call(obj, 1, 2))
// 6

bind

Function.bind方法调用时,将this指针指向方法第一个参数,后续传参直接传,返回函数

const add = (a, b) => {
  return a + b + this.c
}

const obj = { c: 3 }
// Function.bind(newThis, ...args)
console.log(add.bind(obj, 1, 2))
// [Function: bound add]
console.log(add.bind(obj, 1, 2)())
// 6

23528764_0_final.png