zoukankan      html  css  js  c++  java
  • js实现参数定长/不定长的柯里化

    文章原文: https://www.cnblogs.com/yalong/p/14298085.html

    题目1:把一个计算加法的函数fn 进行柯里化,其中fn 分为 参数个数固定 和 参数个数不固定两种

    参数个数固定的柯里化实现:

      function fn(a, b, c) {
        return a + b + c
      }
      function curry(fn) {
        // 获取原函数的参数长度
        const argLen = fn.length;
        // 保存预置参数, 当预置参数 有三个的时候 直接返回了函数,需要单独执行一次
        const presetArgs = [].slice.call(arguments, 1)
        // 返回一个新函数
        return function() {
          // 新函数调用时会继续传参
          const restArgs = [].slice.call(arguments)
          const allArgs = [...presetArgs, ...restArgs]
          if (allArgs.length >= argLen) {
            // 如果参数够了,就执行原函数
            return fn.apply(null, allArgs)
          } else {
            // 否则继续柯里化
            return curry.call(null, fn, ...allArgs)
          }
        }
      }
    
      // 用例一
      let c1 = curry(fn, 1);
      let c2 = curry(c1, 2);
      let c3 = curry(c2, 3);
      console.log(c3()) // 6
    
      // 用例二
      let curried = curry(fn);
      console.log(curried(1, 2, 3)) // 6
      console.log(curried(1, 2)(3)) // 6
      console.log(curried(1)(2, 3)) // 6
      console.log(curried(1)(2)(3)) // 6
    
      // 用例三
      // 注意这个, 因为初始的时候 把参数全部传进去了,导致返回的是一个函数, 没能走到 apply 的立即执行
      console.log(curry(fn, 1, 2, 3)()) // 6
      console.log(curry(fn, 1, 2)(3)) // 6
      console.log(curry(fn, 1)(2, 3)) // 6
      console.log(curry(fn, 1)(2)(3)) // 6
    

    参数个数不固定的柯里化实现

     function curry(fn) {
      // 保存预置参数
      const presetArgs = [].slice.call(arguments, 1)
      // 返回一个新函数
      function curried () {
        // 新函数调用时会继续传参
        const restArgs = [].slice.call(arguments)
        const allArgs = [...presetArgs, ...restArgs]
        // 下面这个相当于 return currl(fn, ...allArgs)
        return curry.call(null, fn, ...allArgs)
      }
      // 重写toString
      curried.toString = function() {
        return fn.apply(null, presetArgs)
        // 下面这个是一样的
        // return fn.call(null, ...presetArgs)
      }
      return curried;
    }
    
    function fn() {
      return [...arguments].reduce((prev, curr) => {
        return prev + curr
      }, 0)
    }
    var add = curry(fn);
    console.log(add(1)(2)(3)(4)) // 10
    console.log(add(1, 2)(3, 4)(5, 6)) // 21
    

    题目2: 实现add(1)(2)(3)(4)的打印结果为10,并且要求可以随意调用,不过每次只传一个参数,如add(1)(2)(3)(4)(5)的打印结果为15
    实现代码如下:

    function add(x) {
        let sum = x;
        let tmp = function (y) {
            sum = sum + y;
            return tmp;
        };
        tmp.toString = function () {
            return sum;
        };
        return tmp;
    }
    console.log(add(1)(2)(3)) // 6
    console.log(add(1)(2)(3)(4)) // 10
    console.log(add(1)(2)(3)(4)(5)) // 15
    

    题目3: 实现add(1, 2)(3)的打印结果为6,add(1)(2, 3, 4)(5) 结果为15, 意思就是 传递的参数个数不固定
    实现代码如下:

    function add () {
        let args = [...arguments];
        let fn = function () {
            args.push(...arguments);
            return fn
        }
        fn.toString=function(){
            return args.reduce((a, b) => {
                return a + b
            })
        }
        return fn
    }
    console.log(add(1, 2)(3)) // 6
    console.log(add(1)(1,2,3)(2)) // 9
    console.log(add(1)(2, 3, 4)(5)) // 15
    

    上面用到了toString 这里就联想到了valueOf 这两者的区别简单来说如下:

    • valueOf():返回最适合该对象类型的原始值
    • toString(): 将该对象的原始值以字符串形式返回

    这两个方法一般是交由JS去隐式调用,以满足不同的运算情况。
    在数值运算里,会优先调用valueOf(),如a + b
    在字符串运算里,会优先调用toString(),如alert(c)。
    当然更深入的说法还有,不过这里就不讨论了。

  • 相关阅读:
    生成4位随机验证码工具类
    MD5加随机盐工具类
    Excel文件解析工具类
    实践作业4:Web测试实践(小组作业)记录4
    实践作业4:Web测试实践(小组作业)记录3
    实践作业4:Web测试实践(小组作业)记录2
    实践作业4:Web测试实践(小组作业)记录1
    实践作业3:白盒测试实践(小组作业)记录3
    实践作业3:白盒测试实践(小组作业)记录2
    实践作业3:白盒测试实践(小组作业)记录1
  • 原文地址:https://www.cnblogs.com/yalong/p/14298085.html
Copyright © 2011-2022 走看看