柯里化的实现

柯里化的实现

面试中经常会遇到这个题目:
写一个函数,实现可多次调用,并且不限制参数个数

add(1, 2, 3, 4); //10
add(1, 2)(3)(4, 5, 6); //21
add(1)(2)(3)(4)(5); //15

最终代码:

function curry(fn) {
  // 保存预置参数
  const presetArgs = [].slice.call(arguments, 1);
  // 返回一个新函数
  function curried() {
    // 新函数调用时会继续传参
    const restArgs = [].slice.call(arguments);
    const allArgs = [...presetArgs, ...restArgs];
    return curry.call(null, fn, ...allArgs);
  }
  // 重写toString
  curried.toString = function () {
    return fn.apply(null, presetArgs);
  };
  return curried;
}

function dynamicAdd() {
  return [...arguments].reduce((prev, curr) => {
    return prev + curr;
  }, 0);
}
var add = curry(dynamicAdd);

const val = add(1)(2)(3)(4);
alert(val); //10
const val2 = add(5)(10, 20, 40, 15);
alert(val2); //90

实现原理主要是运用了以下方法:

  1. 闭包
  2. 重写 toString()方法
  3. call,apply 更改函数 this 指向

思路

使用 argments 接收参数,然后利用闭包的特性,所以在返回的函数当中储存的那个 presetArgs 始终是上一次运行函数时传入的参数列表,也就是说在调用 add(1)的时候,函数中的 presetArgs 其实什么都没有,是个空数组。在调用 add(1)(2)的时候,presetArgs 的值保存了两个,一个是[],一个是[1],所以他才能在多次调用的时候一直都能往 presetArgs 里面塞参数,并且由于闭包,返回的函数里面的那个 fn 其实一直指向的都是 dynamicAdd 这个传入的参数。最后都是处理数据的永远都是这个函数,使用apply是改变传入的方法的this指向,从而进行调用。
为什么要重写返回的函数的toString?
直接打印函数的话会输出该函数的函数体,运用alert()方法会将函数体隐式转换成字符串的思路来重写toString方法,从而在实现传入多少个值最后都会输出计算结果
tips: 高版本chrome浏览器已经不会对console.log里面参数进行字符串的隐式转换了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易风920

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值