zoukankan      html  css  js  c++  java
  • 函数柯理化

    //函数柯理化  其本质是降低通用性,提高适用性,其实是对闭包的极致应用
    //原理:利用闭包保存一部分参数,返回一个包含了一部分参数的闭包。
    //适用场景: ...
    
    function connect(a, b, c, d,e,f,g) {
        console.log(`${a}-${b}-${c}-${d}-${e}-${f}-${g}`);
    }
    
    //在闭包中,A闭包 由 B函数生成
    //使用闭包可以引用函数的变量对象这一性质
    //把闭包中存的变量和闭包接受的实参组合起来,传入目标函数
    //简易版
    function simpleCurry(fn){
        let args = [].slice.call(arguments, 1);
        return function () {
            fn.apply(this, args.concat([].slice.call(arguments)))
        }
    }
    
    //只可以分成两步,如果要可以分成任意层,就得用递归了
    // simpleCurry(connect, 1, 2,5,67,8,4)(3);
    // simpleCurry(connect, 1)(2, 3,4,5,6, 28);
    
    //完整版,接受N层闭包,由于层数不定,递归也必须用到
    //递归的过程中不断的 聚集参数,直到参数达到目标函数需要的个数,就执行函数
    //如何知道函数接受的理想参数个数  fn.length
    function curry(fn, args){
        let length = fn.length; //目标函数理想的参数个数
        let allArgs = args || [];
        return function () {
            let _args = [].slice.apply(arguments);
            let _allArgs = allArgs.concat(_args)
            //未达到理想参数个数就继续聚集参数, 达到了参数的个数,就可以运行目标函数
            if (_allArgs.length < length){
                //聚集参数的过程
                return curry.call(this, fn, _allArgs)
            }
            else{
                fn.apply(this, _allArgs);
            }
        }
    }
    
    curry(connect)(2, 3, 4, 5)(6, 1)(2);
    
    //如果不想按顺序传入,则可以先用占位符,后面再填入数据
    //比如
    /**
     * 
    let fn = curry(function(a, b, c) {
        console.log([a, b, c]);
    });
    
    fn("a", _, "c")("b") // ["a", "b", "c"]
     * 
     * 
     */
    let _;
    function curry2(fn, args){
        let allArgs = args || [];
        let length = fn.length;
        return function () {
            let _args = [].slice.call(arguments);
            let _allArgs = [].slice.call(allArgs);
            //在这里来调整参数的位置, 如果前面有占位符就向前补位
    
            if (_args.indexOf(_) !== -1){
                //有占位符  就直接concat
                _allArgs = _allArgs.concat(_args);
            }
            else{
                    //没有占位符,说明这段参数可以向前补位
                _allArgs.forEach((v, i) => {
                    if (v === _ && _args.length != 0) {
                        _allArgs.splice(i, 1, _args.shift());
                    }
                })
                //剩下的还是添加进参数里面
                if (_args.length != 0){
                    _allArgs = _allArgs.concat(_args);
                }
            }
                //是否达到理想参数个数  以及是否还含有空位
            if (_allArgs.length < length || _allArgs.indexOf(_) !== -1){
                //继续聚集参数
                return curry2.call(this, fn, _allArgs);
            }
            else{
                fn.apply(this, _allArgs);
            }
        }
    }
    
    curry2(connect)(2, _, 4, 5)(_, 1)(_)("占位1", "占位2")("占位3");
    
  • 相关阅读:
    贪心法解活动安排问题
    求两个等长的已排序数组的中位数(《算法导论》P113习题9.3-8)
    0-1背包问题
    动态规划法解最长公共子序列问题
    动态规划法解矩阵链乘问题
    常见的算法设计策略
    A*算法与8数字谜题(参见《算法》P226习题2.5.32)
    keepalive+redis 主从高可用
    sharding-jdbc 读写分离+水平分表
    hash一致算法原理
  • 原文地址:https://www.cnblogs.com/chenlei987/p/10775077.html
Copyright © 2011-2022 走看看