丁鹿学堂:javascript函数式编程探究:函数柯里化

65 阅读2分钟
函数式编程之函数柯里化

函数的柯里化,简单来说把接受多个参数的函数,通过一系列操作,变成接收单一参数的函数,但是不影响最终的结果。

函数柯里化的使用场景

我们说本来函数支持多个参数挺好的,干嘛费力不讨好的搞什么柯里化呢?一个技术或者技巧的出现,必然是为了解决实际问题。

场景一:如果一个函数a必须接收一个参数才能执行,但是这个函数又是作为回调去给b使用,这个时候就没办法传参了。

比如a作为回调传给promise的then方法,此时a就没有办法再接收参数了,只能利用bind去调用生成一个新的函数,同时传参一个参数。bind就是实现了柯里化

function a(b){
  console.log(b)
}
Promise.resolve().then(a.bind(this,12))

场景二:如果一个函数要接收两个参数,但是发现第一个参数其实是固定的,我们就可以通过柯里化来简化函数

比如我们要计算1加上任意一个整数的结果

function add(a,b){
  return a + b
}

这个时候我们发现a永远是传1的,为了优化代码,我们可以使用bind去柯里化函数

let fn2 = add.bind(this,1)
  fn2(2) // 3
最简单的柯里化实现

最简单的就是先接收一个固定参数,然后函数内部再返回一个新的函数,这个函数接收的是剩余的参数。通过函数多次调用实现单一参数的相同结果。

function curry(num1){
  return function(num2){
    return num1 + num2
  }
}
function add(num1,num2){
  return num1 +num2
}
let num1 = add(1,2)
let num2 = curry(1)(2)
console.log(num1)
console.log(num2)
手写实现bind,了解柯里化原理
Function.prototype.bind2 = function (thisArrow){
  // 如果bind的调用者不是函数,则不执行
  if(typeof this !== 'function'){
    return false
  }
  // bind返回的是新函数
  let that = this
  // arguments类数组保存了所有参数,我们取除了第一个的剩余,因为第一个参数是绑定的this
  let args = Array.prototype.slice.call(arguments,1)
  // 这个新函数是改变了this指向的原函数
   return function(){
      return that.apply(thisArrow,[...args,...arguments])
   }
}

let obj1 = {
  name:'zhangsan',
  fn(num,num2){
    console.log(this.name + num+num2)
  }
}
let obj2 = {
  name:'lisi'
}
obj1.fn(1,2)
let fn2 = obj1.fn.bind(obj2,1)
fn2(2)