美文网首页
柯里化思想

柯里化思想

作者: 池鱼_故渊 | 来源:发表于2021-04-29 11:36 被阅读0次

    概念

    • 柯里化可以让我们给函数传递较少的参数得到一个已经记住的某个固定参数的新函数

    • 这是一种对函数参数的缓存

    • 让函数变的更灵活,让函数的粒度更小

    • 可以把多元函数(指多个参数)转化成一元函数(指一个参数),可以组合使用函数,使其产生强大的功能

      这是一种预先处理的思想(形成一个不被释放的闭包,把一些信息存储起来,以后基于作用域链,访问到事先存储的信息,然后进行相关的处理,所有符合这种模式都被成为柯里化函数)

    先来看看 reduce

    数组 reduce 方法:在遍历数组的过程中,可以积累上一次处理的结果,基于上次处理的结果继续遍历

    // array.reduce([callback],[initialValue])
    var arr = [10, 20, 30, 40];
    var res = arr.reduce(function (result, item, index) {
      // [initialValue] 初始值不传递,result默认的是数组第一项,然后reduce从数组第二项开始遍历
      // 每遍历一次 回调函数被触发执行一次
      // + result 存储的是上一次回调函数返回的结果(除了第一次初始值或者数组第一项)
      // + item 当前遍历的一项
      // + index 当前遍历一项的索引
      return item + result;
    });
    
    var res2 = arr.reduce((result, item) => {
      // 如果传递了初始值,则result第一次的结果就是初始值,item从数组第一项开始遍历
      return item + result;
    }, 0);
    

    模拟实现 reduce

    Array.prototype.reduceTest = function reduceTest(callback, initial) {
      var self = this; // this =>arr
      var i = 0;
      // callback 必须是函数
      if (typeof callback !== "function")
        throw new TypeError("callback must be an function");
      // 判断是否有初始值
      if (typeof initial === "undefined") {
        // 如果没有初始值 initial 初始值为 数组 的第一项,然后从数组第二项开始遍历
        initial = self[0];
        i = 1;
      }
      for (; i < self.length; i++) {
        var item = self[i];
        index = i;
        initial = callback(initial, item, index);
      }
      return initial;
    };
    

    用柯里化的思想和 reduce 实战一道题目

    求和;
    var sum = curring(10);
    console.log(sum(20));
    console.log(sum(20, 30));
    
    function curring(x) {
      // 利用闭包机制存储x
      return function (...args) {
        args.unshift(x);
        return args.reduce((result, item) => {
          return result + item;
        });
      };
    }
    

    组合函数

    组合函数是函数式编程的重要概念,处理数据的函数就像是管道一样连接起来,然后数据穿过管道最终得到结果

    const add1 = (x) => x + 1;
    const add2 = (x) => x * 3;
    const add3 = (x) => x / 2;
    // 然后我们构建一个组合函数
    const operat = compose(add1, add2, add3);
    operat(0); // 相当于 add3(add2(add1(0)))
    // 那么这个compose函数怎么编写呢?
    
    function compose(...funs) {
      return function operat(x) {
        if (funs.length === 0) return x;
        if (funs.length === 1) return funs[0](x);
        // reduce 数组 从左向右执行  reduceRight 数组从右向左执行
        return funs.reduceRight(function (result, item) {
          if (typeof item !== "function") return result;
          return item(result);
        }, x);
      };
    }
    var operate = compose(div2, mul3, add1);
    var result = operate(0);
    console.log(result);
    
    // funs :存储需要指向函数的顺序 最后面的函数优先执行
    // 执行compose 只是把要执行的函数存储起来,还没有执行
    // 返回一个operat 处理函数,执行函数,并且传递初始值,才按照之前存储的顺序依次执行
    // 依旧是用到了闭包的思想
    

    模拟实现函数柯里化

    function curry(func) {
      return function curried(...args) {
        // 判断实参和形参的个数 如果参数大于或者等于,那个直接执行下面的返回函数把参数传进去
        // 否则进入判断,把参数合并再传入函数中,
        if (args.length < func.length) {
          return function () {
            return curried(...args.concat(Array.from(arguments)));
          };
        }
        return func(...args);
      };
    }
    
    function getSum(a, b, c) {
      return a + b + c;
    }
    
    const curried = curry(getSum);
    console.log(curried(1, 2, 3));
    console.log(curried(1)(2, 3));
    

    命令式编程和函数式编程的区别

    命令式编程:自己编写代码,管控步骤和逻辑(自己可以灵活掌握步骤)

    函数式编程:具体的实现步骤已经被封装成方法,我们只需要调用方法获取结果即可,无需关注怎么实现的。
    弊端:无法灵活掌握执行的步骤

    相关文章

      网友评论

          本文标题:柯里化思想

          本文链接:https://www.haomeiwen.com/subject/tuairltx.html