函数柯里化

今天接触到了一个以前没据说过的东东,感受很好玩~分享给你们~为了完全的了解一下相关概念,特地拜读了一下张鑫旭大神的相关文章连接以下~:数组

http://www.zhangxinxu.com/wordpress/?p=3048浏览器

感谢大神分享,本文将截取大神分享的部分及加上本身的小小理解~ 先发一波定义~(源自百度百科)bash

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,而且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。app

大神用于函数柯里化用的比喻至关的形象很是有助于理解~ “柯里化”就像某些官员的把戏,官员要弄7个老婆,碍于国策(一夫一妻)以及年老弟衰,表面上就1个老婆,实际上剩下的6个暗地里消化,代码表示以下:wordpress

var curring = function(fn){
	// fn 指官员消化老婆的手段
	var args = [].slice.call(arguments,1); // 截取arguments中的第一个生成一个数组,也就是当前语境下的明面上的合法老婆
	return function(){
		// 将已有的参数和新传进来的参数合并为一个数组,对应已有的合法老婆和新搞定的老婆
		var newArgs = args.concat([].slice.call(arguments));
		// 将全部的参数newArgs绑定给fn~ 
		return fn.apply(null,newArgs);
	}
}

// 下面为官员如何搞定7个老婆作测试
// 得到合法老婆
var getWife = currying(function(){
	var allWife = [].slice.call(arguments);
	console.log(allWife.join(';'))
},"合法老婆");
// 得到其余6个老婆
getWife("小老婆1","小老婆2","小老婆3","小老婆4","小老婆5","小老婆6");
// 换一批老婆 
getWife("大老婆","小老婆","俏老婆","刁蛮老婆","乖老婆","送上门老婆");
// 再换一批老婆
getWife("超越韦小宝的老婆");
复制代码

效果是这样的~函数

不管输入多少个参数,都会打印输出,且都会带着第一个参数~ 上文代码fn.apply(null,newArgs)中的null本是应该制定fn中this的指向的对象,没有因此就用null啦,算是一个小技巧~测试

理解理解以后再想一想,这个东西有什么用啊~~ 柯里化有三个常见的应用:ui

  • 参数复用(上文代码中的合法老婆)
  • 提早返回 这里举个很实用的例子,兼容现代浏览器以及IE浏览器的事件添加方法:
var addEvent = function(el, type, fn, capture) {
    if (window.addEventListener) {
        el.addEventListener(type, function(e) {
            fn.call(el, e);
        }, capture);
    } else if (window.attachEvent) {
        el.attachEvent("on" + type, function(e) {
            fn.call(el, e);
        });
    } 
};
复制代码

上面的方法有什么问题呢?很显然,咱们每次使用addEvent为元素添加事件的时候,(eg. IE6/IE7)都会走一遍if...else if ...,其实只要一次断定就能够了,怎么作?–柯里化。改成下面这样子的代码:this

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);
            });
        };
    }
})();
复制代码

初始addEvent的执行其实只实现了部分的应用(只有一次的if...else if...断定),而剩余的参数应用都是其返回函数实现的,典型的柯里化。spa

  • 第三个常见应用: 延迟计算
var curryWeight = function(fn) {
    var _weight = [];
    return function() {
        if (arguments.length === 0) {
            return fn.apply(null, _weight);
        } else {
            _weight = _weight.concat([].slice.call(arguments));
        }
    }
};
var weight = 0;
var addWeight = curryWeight(function() {
    var i=0; len = arguments.length;
    for (i; i<len; i+=1) {
        weight += arguments[i];
    }
});

addWeight(2.3);
addWeight(6.5);
addWeight(1.2);
addWeight(2.5);
addWeight();    //  这里才计算

console.log(weight);    // 12.5
复制代码

先传入参数,直到调用的时候才执行计算~

今天的分享就先到这里了~愿与各位共勉~

相关文章
相关标签/搜索