Skip to content

Latest commit

 

History

History
122 lines (82 loc) · 4.42 KB

柯里化.md

File metadata and controls

122 lines (82 loc) · 4.42 KB

柯里化

**柯里化(Currying)**是 lambda 演算中的一个概念。

柯里化是一个函数,它一次接受一个参数,并返回一个新函数,该函数期待下一个参数。它是一种函数转换,将 f(a,b,c) 转换为可以被以 f(a)(b)(c) 的形式进行调用。

JavaScript 中的柯里化是什么?

柯里化简单地说就是计算具有多个参数的函数,并将它们分解为具有单个参数的函数序列。

换句话说,柯里化是一个函数,而不是一次获取所有参数,获取第一个参数并返回一个新函数,该函数获取第二个参数并返回一个新函数,该函数获取第三个参数,以此类推,直到所有参数都完成。

为什么要用柯里化?

柯里化之所以理想,有几个原因:

  • 柯里化是一种检查方法,确保你在继续之前得到了所需的一切
  • 它可以帮助您避免一次又一次地传递同一个变量(参数复用)
  • 它将您的函数划分为多个较小的功能,可以处理一项职责。这使你的函数更纯粹,更不容易出错和产生副作用
  • 在函数式编程中,它用于创建高阶函数
  • 这可能是个人喜好,增强代码可读性

实现柯里化

柯里化是一个接受多个参数的函数。它将把这个函数转换成一系列函数,每个小函数都接受一个参数。

一个简单累加数示例:

// 非柯里化
const add = (a, b, c) => {
  return a + b + c
}
console.log(add(2, 3, 5)) // 10

// 柯里化
const addCurry = (a) => {
  return (b) => {
    return (c) => {
      return a + b + c
    }
  }
}

console.log(addCurry(2)(3)(5)) // 10

以上实现柯里化更简便的方法是,利用 ES6 的箭头函数特性帮助我们编写更少的代码:

const addCurry = (a) => (b) => (c) => a + b + c

console.log(addCurry(2)(3)(5)) // 10

高级柯里化:

const curry = (fn) => {
  return (curried = (...args) => {
    if (fn.length !== args.length) {
      return curried.bind(null, ...args)
    }
    return fn(...args)
  })
}

const totalNum = (x, y, z) => x + y + z
const curriedTotal = curry(totalNum)

console.log(curriedTotal(10)(20)(30)) // 60

在上面的例子中,我们创建了一个需要固定数量参数的函数。

它接收一个函数 curry 作为外部函数。这个函数是一个包装函数。它返回另一个名为 curried 的函数,该函数接收带有扩展运算符 (...args) 的参数,并比较函数长度 fn.length

函数长度意味着无论我们在这里传递多少个参数,它都会反映在函数的 length 属性中。

但是每次参数都会增加。如果我们需要的参数数量不相等,它将返回 curried。如果我们调用 bind,就会创建一个新函数并传递 (...args)

注意bind 创建了一个新函数。

示例:操作 DOM

以下是一个简单的使用柯里化函数操作 DOM 示例:

const updateElemText = (id) => (content) => (document.querySelector(`#${id}`).textContent = content)

const updateHeaderText = updateElemText('header')
updateHeaderText('Hello D.O!')

柯里化与偏函数

既然你知道了柯里化的工作原理,那么柯里化和偏函数(partial application)之间有什么区别?

  • 柯里化:一个接受多个参数的函数。它将把这个函数转换成一系列函数,其中每个小函数将接受一个参数,直到所有参数都完成。
  • 偏函数:当给定的参数少于预期的参数时,函数将转化为偏函数,并返回一个期望剩余参数的新函数。

示例:

const addPartial = (x, y, z) => x + y + z

const partialFunc = addPartial.bind(this, 2, 3)
partialFunc(5) // 10

当函数传递的某些参数不完整时,它被称为偏函数。

柯里化和偏函数并没有真正的区别;它们是相关的,但它们有不同的理论和应用。

更多资料