柯里化定义

柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数的新函数

fn(1)(2)(3)(4)
fn(1, 2)(3)(4)
fn(1, 2, 3)(4)
fn(1, 2, 3, 4)

柯里化的思想就是把参数缓存起来,等到特定的时机来计算返回结果,比如实现一个 add 方法

add(1)(2)(3) = 6
add(1, 2)(3) = 6
add(1, 2, 3) = 6
function add(...args) {
  function _add(...args2) {
    return add.apply(null, [...args, ...args2])
  }
  // 隐式转换,先调用valueOf再调用toString
  _add.valueOf = _add.toString = function() {
    return args.reduce((a, b) => (a + b))
  }
  return _add
}

console.log(add(1)(2)(3))  // 6
console.log(add(1, 2)(3))  // 6
console.log(add(1, 2, 3))  // 6

柯里化应用

延迟执行

举个例子,绑定dom事件的时候,我们经常做了一个兼容的写法,例如

function addEvent(el, type, fn, isCapture = false) {
  if (window.addEventListener) {
    el.addEventListener(type, fn, isCapture)
  } else {
    el.attachEvent(`on${type}`, fn)
  }
}

这样有一个缺点就是每次调用 addEvent 方法都需要判断再绑定,这时候可以利用柯里化来实现

const addEvent = (() => {
  if (window.addEventListener) {
    return (el, type, fn, isCapture = false) => {
      el.addEventListener(type, fn, isCapture)
    }
  } else {
    return (el, type, fn) => {
      el.attachEvent(`on${type}`, fn)
    }
  }
})()
  • 提前返回 – 使用函数立即调用进行了一次兼容判断(部分求值),返回兼容的事件绑定方法
  • 延迟执行 – 返回新函数,在新函数调用兼容的事件方法。等待addEvent新函数调用,延迟执行