美文网首页
js函数柯里化

js函数柯里化

作者: 攻城熊 | 来源:发表于2021-02-02 15:04 被阅读0次

    柯里化: 一个函数原本有多个参数, 之传入一个参数, 生成一个新函数, 由新函数接收剩下的参数来运行得到结构.

       var add = function (x) {
            return function (y) {
                return x + y
            }
        }
        var increment = add(1)  // 参数x被封印在了返回的新函数中,值为1不变化
        var addTen = add(10)   // 参数x被封印在了返回的新函数中,值为10不变化
        increment(2) // 3
        addTen(10)  // 12
        add(10)(10) // 20
        increment(1)  // 2
    

    为什么要使用科里化? 为了提升性能. 使用科里化可以缓存一部分能力.
    高阶函数: 一个函数参数是一个函数, 该函数对参数这个函数进行加工, 得到一个函数, 这个加工用的函数就是高阶函数.
    Array.prototype.map((item,index,arr)=>{}) //高级函数的参数为函数

    柯里化函数原理其实是 闭包,
    函数即能力, 将某些能力作为新能力的基础能力
    有点类似于层层递进的能力等级
    柯里化函数返回的是函数, 是下一次操作的调用者

    柯里化的对比

    // 存在硬编码问题的函数
    function checkAge (age) {
        const min = 18
        return age >= min
    }
    console.log(checkAge(20))
    
    // 使用普通纯函数解决方案
    function checkage (min, age) {
        return age >= min
    }
    console.log(checkAge(18, 20))
    
    // 使用闭包配合柯里化解决方案
    function checkAge (min) {
        return function (age) {
            return age >= min
        }
    }
    const checkAge18 = checkAge(18)
    console.log(checkAge18(20))
    
    

    思考: 虚拟DOM的render方法
    思考: Vue 项目模版转换为抽象语法树需要执行几次?
    页面一开始加载需要渲染
    每一个属性( 响应式 )数据在发生变化的时候需要渲染
    watch,computed等等
    之前的代码 每次需要渲染的时候,模版就会解析一次

    reder 的作用是将虚拟DOM转换为真正DOM加到页面中
    虚拟DOM可以降级理解为 AST
    一个项目运行时候,模版是不会变的,就表示 AST 是不会变的

    我们可以将代码进行优化,将虚拟DOM缓存起来,生成一个函数,函数只需要传入数据,就可以得到真正的DOM.

    function ad(a) {
        return function(b) {
            return function(c) {
                return a + b + c;
                // ... 不限制层级如何处理?  
            }
        }
    }
    // 先理解一下toString()
    function add (a) {
        function sum(b) { // 使用闭包
            a = a + b; // 累加
            return sum;
        }
        sum.toString = function() { // 重写toSting() 方法
            return a;
        }
        return sum; // 返回一个函数
    }
     
    console.log(add(1)(3)) // 4
    console.log(add(1)(3)(5)) // 9
     
    // 解决方式
    function add() {
        // 第一次执行时,定义一个数组专门用来存储所有的参数
        var _args = [].slice.call(arguments);
        // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
        var adder = function () {
            var _adder = function() {
                [].push.apply(_args, [].slice.call(arguments));
                return _adder;
            };
            //  利用隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
            //  打印函数时会自动调用 toString()方法
            _adder.toString = function () {
                return _args.reduce(function (a, b) {
                    return a + b;
                });
            }
            return _adder;
        }
        return adder.apply(null, [].slice.call(arguments));
    }
    // 输出结果,可自由组合的参数
    console.log(add(1, 2, 3, 4, 5));  // 15
    console.log(add(1, 2, 3, 4)(5));  // 15
    

    字符串正则判断的应用

    function checkEmail(email) {
        return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(email);
    }
    function check(targetString, reg) {
        return reg.test(targetString);
    }
    check(/^1[34578]\d{9}$/, '14900000088');
    check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'test@163.com');
    
    // 如何封装通用能力 ?
    
    // 正常正则验证字符串 reg.test(txt)
    // 函数封装后
    function check(reg, txt) {
        return reg.test(txt)
    }
    
    check(/\d+/g, 'test')       //false
    check(/[a-z]+/g, 'test')    //true
    
    // Currying后
    function curryingCheck(reg) {
        return function(txt) {
            return reg.test(txt)
        }
    }
    var hasNumber = curryingCheck(/\d+/g)
    var hasLetter = curryingCheck(/[a-z]+/g)
    

    柯里化可以让我们给一个函数传递较少的参数,得到一个已经记住了某些固定参数的新函数,者就是柯里化的核心。在柯里化内部就是使用闭包,对函数的参数进行缓存。柯里化让函数变得更灵活,因为我们可以通过一个函数生成一些细粒度更小的函数。这么做的目的是为了在后续函数组合的时候在使用。柯里化可以把多元函数转换成一元函数,目的是可以组合使用函数产生强大的功能。

    lodash_curry函数柯里化的实现? 有兴趣的可以查看lodash源码,这里就不讲了哈.

    相关文章

      网友评论

          本文标题:js函数柯里化

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