晴明的博客园 GitHub      CodePen      CodeWars     

[js] 柯里化(局部套用)(currying)

#参数复用

#

        function curry(fn){
            var args = Array.prototype.slice.call(arguments, 1);
            return function(){
                //curriedAdd   这两个arguments是不同的,但是通过concat合并了
                var innerArgs = Array.prototype.slice.call(arguments),
                    finalArgs = args.concat(innerArgs);
//              没有数组处理,实际上传进去的参数也就前边2个
                return fn.apply(null, finalArgs);
            };
        }
    
        function add(num1, num2){
            console.log(arguments);
            return num1 + num2;
        }
        
        var curriedAdd = curry(add, 5);
        console.log(curriedAdd(3));   //8

        var curriedAdd2 = curry(add, 5, 12);
        console.log(curriedAdd2());   //17

 #

            function spyOn(func) {
                var count = 0;
                var args = [];
                var results = [];
                var spy = function() {
                    var innerArgs = Array.prototype.slice.call(arguments);
                    args = args.concat(innerArgs);
                    var result = func.apply(null,innerArgs);//第一个参数还可写this
                    results = results.concat(result);
                    count++;
                    return result;
                };
                spy.callCount = function() {
                    return count;
                }
                spy.wasCalledWith = function(x) {
                    return args.indexOf(x) > -1;
                }
                spy.returned = function(y) {
                    return results.indexOf(y) > -1;
                }
                return spy;
            }

            function adder(n1, n2) {
                return n1 + n2;
            }
            var adderSpy = spyOn(adder);
            console.log(adderSpy(2, 4)); // returns 6
            console.log(adderSpy(3, 5)); // returns 8
            console.log(adderSpy.callCount()); // returns 2
            console.log(adderSpy.wasCalledWith(4)); // true
            console.log(adderSpy.wasCalledWith(0)); // false
            console.log(adderSpy.returned(8)); // true
            console.log(adderSpy.returned(0)); // false

 

#

            var currying = function(fn) {
                // fn 指官员消化老婆的手段
                var args = [].slice.call(arguments, 1);
                // args 指的是那个合法老婆
                return function() {
                    // 已经有的老婆和新搞定的老婆们合成一体,方便控制
                    var newArgs = args.concat([].slice.call(arguments));
                    // 这些老婆们用 fn 这个手段消化利用,完成韦小宝前辈的壮举并返回
                    return fn.apply(null, newArgs);
                };
            };
            // 下为官员如何搞定7个老婆的测试
            // 获得合法老婆
            var getWife = currying(function() {
                var allWife = [].slice.call(arguments);
                // allwife 就是所有的老婆的,包括暗渡陈仓进来的老婆
                console.log(allWife.join(";"));
            }, "合法老婆");
            // 获得其他6个老婆
            getWife("大老婆", "小老婆", "俏老婆", "***蛮老婆", "乖老婆", "送上门老婆");
            // 换一批老婆
            getWife("超越韦小宝的老婆");

#

            var smallKenan = function(action) {
                console.log(arguments);
                var bigKenan = function(doing) {
                    console.warn(arguments);
                    var result = "";
                    if (action === "take drugs") {
                        if (doing === "bathWithGirlFriend") {
                            result = "尖叫,新一,你这个色狼,然后一巴掌,脸煮熟了~";
                        } else if (doing === "pointOutKiller") {
                            result = "新一,这个案子就交给你的,快点找出谁是凶手吧~";
                        }
                    } else {
                        if (doing === "bathWithGirlFriend") {
                            result = "来吧,柯南,一起洗澡吧~";
                        } else if (doing === "pointOutKiller") {
                            result = "小孩子家,滚一边去!";
                        }
                    }
                    console.log(result);
                    return arguments.callee; // 等同于return bigKenan
                };
                console.info(bigKenan);
                return bigKenan;
            };
            smallKenan("take drugs")("bathWithGirlFriend")("pointOutKiller");
            

#提前返回

            var addEvent = (function() {
                if (window.addEventListener) {
                    return function(el, sType, fn, capture) {
                        el.addEventListener(sType, function(e) {
                            fn.call(el, e);
                        }, (capture));
                    };
                } else if (window.attachEvent) {
                    return function(el, sType, fn, capture) {
                        el.attachEvent("on" + sType, function(e) {
                            fn.call(el, e);
                        });
                    };
                }
            })();

#延迟计算

            var averageWeight = 0;
            var curryWeight = function(fn) {
                //console.log(fn);
                console.warn(arguments); //就是fn
                var _fishWeight = [];
                return function() {
                    //这部分也就是addWeight
                    console.log(arguments); //与fn不是同一个东西
                    if (arguments.length === 0) {
                        return fn.apply(null, _fishWeight); //获取参数
                    } else {
                        _fishWeight = _fishWeight.concat([].slice.call(arguments));
                    }
                    //                    省去额外的这步addWeight()
                    //                    _fishWeight = _fishWeight.concat([].slice.call(arguments));
                    //                    console.info(_fishWeight);
                    //                    return fn.apply(null, _fishWeight);
                }
            };
            var fishWeight = 0;
            //等于return的部分
            var addWeight = curryWeight(function() {
                var i = 0;
                len = arguments.length;
                for (i; i < len; i += 1) {
                    averageWeight += arguments[i] / len;
                }
                console.error(averageWeight);
                console.error(arguments);
            });
            //            addWeight(2.3);
            //            addWeight(6.5);
            //            addWeight(1.2);
            //            addWeight(2.5);
            //可以一次传多个参数。
            addWeight(2.3, 6.5, 1.2, 2.5);
            addWeight(); //闭包,_fishWeight不被释放
            console.log(averageWeight); // 3.125
            addWeight(100, 200);
            addWeight();
            console.log(averageWeight); // 55.208333333333336

#bind的实现机制

 

            Function.prototype.bind = function(context) {
                console.log(arguments);
                console.log(context);
                console.log(this);
                var self = this,
                    args = Array.prototype.slice.call(arguments);
                return function() {
                    console.warn(this);
                    self.apply(context, args.slice(1));
                }
            };
            var obj = {
                    "name": "currying",
                    "ha": "wo"
                },
                fun = function() {
                    console.log(this.name);
                }.bind(obj);
            fun(); // currying
            //            if (! function() {}.bind) {
            //                Function.prototype.bind = function(context) {
            //                    var self = this,
            //                        args = Array.prototype.slice.call(arguments);
            //                    return function() {
            //                        return self.apply(context, args.slice(1));
            //                    }
            //                };
            //            }

 

posted @ 2016-04-01 23:57  晴明桑  阅读(219)  评论(0)    收藏  举报