js柯里化二三事

534 阅读3分钟

柯里化是什么?

  1. js柯里化指的是什么?
    通俗点讲:比如一个函数接收两个参数,另一个函数只接收第一个参数,再返回一个函数接收第二个参数。
    那么,这么做的好处是什么呢?请看下面示例:
   //eg1:
    function add(x, y) {
        return x + y;
    }
    add(1,2) //3
    
    function curryingAdd(x) {
        return function(y){
            return x + y
        }
    }
    curryingAdd(1)(2)//3

柯里化应该怎么用?
2. 柯里化函数的特点:
2-1:参数复用(eg2):
解析:假如有很多地方需要验证字母的话,可以直接复用checoutLetter方法。省去了每次都要传正则的麻烦。

 //eg2: 科里话函数与普通函数正则验证字符串的对比:
    function check(reg, txt) {
        return reg.test(txt)
    }
    check(/\d\g/, 'aaaa') //false
    check(/[a-z]/g, 'aaaa')//true

    function curringCheck(reg) {
        return function(txt) {
            console.log(reg.test(txt))
            return reg.test(txt)
        }
    }

    var checoutLetter = curringCheck(/[a-z]/g)
    var checkoutNumber = curringCheck(/\d/g)

    checoutLetter('aaa11') //true
    checoutLetter(123)      //false
    checkoutNumber('aaa')   //false

2-2: 提前确认(eg3):
解析:我们在做项目的过程中,封装一些dom操作可以说再常见不过,上面第一种写法也是比较常见,但是我们看看第二种写法。
它相对第一种写法就是自执行然后返回一个新的函数,这样其实就是提前确定了会走哪一个方法,避免每次都进行判断。

 //eg3:
    var on = function(element, event, handler) {
        if (document.addEventListener) {
            if (element && event && handler) {
                element.addEventListener(event, handler, false);
            }
        } else {
            if (element && event && handler) {
                element.attachEvent('on' + event, handler);
            }
        }
    }

    var on = (function() {
        if (document.addEventListener) {
            return function(element, event, handler) {
                if (element && event && handler) {
                    element.addEventListener(event, handler, false);
                }
            };
        } else {
            return function(element, event, handler) {
                if (element && event && handler) {
                    element.attachEvent('on' + event, handler);
                }
            };
        }
    })();

    //换一种写法可能比较好理解一点,上面就是把isSupport这个参数给先确定下来了
    var on = function(isSupport, element, event, handler) {
        isSupport = isSupport || document.addEventListener;
        if (isSupport) {
            return element.addEventListener(event, handler, false);
        } else {
            return element.attachEvent('on' + event, handler);
        }
    }

2-3: 延迟执行(eg4):
解析:延迟执行,没看太明白有什么应用场景和作用??:
补充:对象参数转换为数组 : Array.prototype.slice.call(arguments)

   //eg4:
    Function.prototype.bind = function (context) {
        var _this = this
        var args = Array.prototype.slice.call(arguments, 1)
        
        return function() {
            return _this.apply(context, args)
        }
    }

    //解析:Array.prototype.slice.call(arguments)能够将arguments转成数组(IE除外)
    //参考:https://www.cnblogs.com/littledu/archive/2012/05/19/2508672.html
    //关于arguments类数组的介绍:https://www.cnblogs.com/minigrasshopper/p/8058679.html
    var a={length:2,0:'first',1:'second'};
    Array.prototype.slice.call(a) //     ["first", "second"]
    var b = Array.prototype.slice.call(a, 1);//  ["second"]
    // console.log(b.concat(Array.prototype.slice.call(a)))// ["second", "first", "second"]

练习: 以一道经典面试题作为收尾:
实现一个add方法,使计算结果能够满足如下预期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;

答案:
    function add() {
        // console.log(arguments, '--arguments--')
        var _args = Array.prototype.slice.call(arguments);      //此处的arguments只接收一个参数,然后将其转化成类数组格式(返回其长度,和将每一项的值存到数组中)
        
        var _adder = function() {
            // console.log(...arguments, '--zhankai---')          //此处的...arguments是将add(),也就是第一个括号以后的所有传参,进行了展开运算 (就是利用了柯里化的一个特性:参数复用)                    
            _args.push(...arguments);
            console.log(_adder, '--adder--')
            return _adder;
        };

        _adder.toString = function () {                        //隐式转化:_adder()方法函数,去调用toString()方法,
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }
        return _adder;
    }
    console.log( add(1)(2)(3) )
    console.log( add(1, 2, 3)(4))
    console.log(add(1)(2)(3)(4)(5))

补充:
什么是隐式转化?以及它的使用场景?
1. js是弱类型语言,即在赋值的同时,也声明了它的使用类型。
2. 当给一个已经赋值的变量,再次赋值时,js会根据固定的规则来进行隐式转换。(这也是弱类型语言的一个特性)
详细介绍:www.jianshu.com/p/f6d3ef905…

   举一个简单的例子帮助大家理解:

    var num = 1;//Number
    var num = '23';//String
    console.log( num)//String  23

总结: 在整篇文章中,我们了解到了js柯里化的三个特性:参数复用,提前确认,延迟执行。大家平时在写代码的过程中,勤加思考,相信大家对柯里化的理解会更上一层楼。
如果觉得对你有帮助,请给作者一点小小的鼓励, 点个赞或者收藏吧。 有需要沟通的请联系我:微信( wx9456d ) 邮箱( allan_liu986@163.com )