JavaScript函数的柯里化(currying)
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/currying.html
什么是js函数的currying /柯里化?
说到js的柯里化,相信很多朋友都会头大。或者不是很清楚。我今天简单的给大家介绍一下。
我用一句话总结函数柯里化,js柯里化是逐步传参,逐步缩小函数的适用范围,逐步求解的过程。
可能对这句话你不是很清楚,那么,我们来看个案例,简单说明一下:
需求:我们写一个函数,将函数的几个参数相加,返回结果!那我们写的函数如下
var concat3Words = function (a, b, c) {
    return a+b+c;
};
函数柯里化呢?是分部求解,先传一个a参数,再传一个b参数,再传一个c参数,最后将这三个参数相加!
var concat3WordsCurrying = function(a) {
    return function (b) {
        return function (c) {
            return a+b+c;
        };
    };
};
我们看输出结果:
console.log(concat3Words("foo ","bar ","baza"));            // foo bar baza
console.log(concat3WordsCurrying("foo "));                  // [Function]
console.log(concat3WordsCurrying("foo ")("bar ")("baza"));  // foo bar baza 函数链式调用
柯里化案例
上面的需求我们稍微变一下。现在我们更进一步,如果要求可传递的参数不止3个,可以传任意多个参数,当不传参数时输出结果?那现在我们用柯里化来简单的实现一下:
var adder = function () {
    var _args = [];
    return function () {
        ) {
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }
        [].push.apply(_args, [].slice.call(arguments));
        return arguments.callee;
    }
};
var sum = adder();
console.log(sum);     // Function
sum(,)();    // 调用形式灵活,一次调用可输入一个或者多个参数,并且支持链式调用
sum();
console.log(sum());   // 1000 (加总计算) 
上面 adder是柯里化了的函数,它返回一个新的函数,新的函数接收可分批次接受新的参数,延迟到最后一次计算。我们可以任意传入参数,当不传参数的时候,输出计算结果!
基础知识普及之arguments
看到上面的柯里化实现,可能有的朋友会有点晕,其实上面也没有什么新的知识,假如你看过我之前写的文章,相信能够理解!apply,call之前都有介绍。前端干货中的第四条,也有提及!唯独arguments前面文章没有介绍。
arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。arguments非常类似Array,但实际上又不是一个Array实例。
我们看一下下面的例子:
function f(a, b, c){
    alert(arguments.length);   // result: "2"
    a = ;
    alert(arguments[]);       // result: "100"
    arguments[] = "haorooms";
    alert(a);                  // result: "haorooms"
    alert(c);                  // result: "undefined"
    c = ;
    alert(arguments[]);       // result: "undefined"
}
f(, );
我们通常用
[].slice.call(arguments, )
将传入参数转为数组。slice是js的一个函数,关于其用法,不会的去查一下!上面的写法相当于Array.prototype.slice.call(arguments, 1);
另外,arguments对象中有一个非常有用的属性:callee。arguments.callee返回此arguments对象所在的当前函数引用。在使用函数递归调用时推荐使用arguments.callee代替函数名本身。arguments就介绍到这里!
通用的柯里化函数
下面这个是通用的柯里化函数
var currying = function (fn) {
    var _args = [];
    return function () {
        ) {
            return fn.apply(this, _args);
        }
        Array.prototype.push.apply(_args, [].slice.call(arguments));
        return arguments.callee;
    }
};
我们可以通过如下函数简单应用一下柯里化:
var multi=function () {
    ;
    , c; c = arguments[i++];) {
        total += c;
    }
    return total;
};
var sum = currying(multi);  
sum(,)();
sum();
console.log(sum());     // 1000  (空白调用时才真正计算)
增加适用性的柯里化
上面我的介绍的是柯里化延迟执行,缩小范围!还有一种是增加了函数的适用性,但同时也降低了函数的适用范围。其通用写法如下:
function currying(fn) {
    var slice = Array.prototype.slice,
    __args = slice.call(arguments, );
    return function () {
        var __inargs = slice.call(arguments);
        return fn.apply(null, __args.concat(__inargs));
    };
}
例如:
function square(i) {
    return i * i;
}
function map(handeler, list) {
    return list.map(handeler);
}
// 数组的每一项平方
map(square, [, , , , ]);
map(square, [, , , , ]);
map(square, [, , , , ]);
例子中,创建了一个map通用函数,用于适应不同的应用场景。显然,通用性不用怀疑。同时,例子中重复传入了相同的处理函数:square。
柯里化改造:
function square(i) {
    return i * i;
}
function map(handeler, list) {
    return list.map(handeler);
}
var mapSQ = currying(map, square);
mapSQ([, , , , ]);
mapSQ([, , , , ]);
mapSQ([, , , , ]);
Function.prototype.bind 方法也是柯里化应用
与 call/apply 方法直接执行不同,bind 方法 将第一个参数设置为函数执行的上下文,其他参数依次传递给调用方法(函数的主体本身不执行,可以看成是延迟执行),并动态创建返回一个新的函数, 这符合柯里化特点。
};
var bar = function () {
    console.log(this.x);
}.bind(foo); // 绑定
bar();
完结,散花
JavaScript函数的柯里化(currying)的更多相关文章
- js高阶函数--判断数据类型、函数胡柯里化;
		
一.判断数据类型: 常见的判断有typeof.instanceof. constructor. prototype,先来看typeof: var a = "hello world" ...
 - 浅谈JavaScript中的柯里化函数
		
首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返 ...
 - JavaScript函数式编程(纯函数、柯里化以及组合函数)
		
JavaScript函数式编程(纯函数.柯里化以及组合函数) 前言 函数式编程(Functional Programming),又称为泛函编程,是一种编程范式.早在很久以前就提出了函数式编程这个概念了 ...
 - Swift函数柯里化(Currying)简谈
		
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多 ...
 - JS 函数的柯里化与反柯里化
		
===================================== 函数的柯里化与反柯里化 ===================================== [这是一篇比较久之前的总 ...
 - 关于arguments对象以及函数的柯里化;
		
1.arguments对象 Arguments是个类似数组但不是数组的对象,说他类似数组是因为其具备数组相同的访问性质及方式,能够由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性 ...
 - JS中的柯里化(currying)
		
何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参 ...
 - JS中的柯里化(currying)     转载自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
		
JS中的柯里化(currying) by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpr ...
 - Python进阶1---高阶函数、柯里化
		
高阶函数 不相等 自定义sort函数 内建函数--高阶函数 #sort函数 def sort2(lst,key = None,reverse = False): res = [] if key is ...
 
随机推荐
- 【机器学习实战 第九章】树回归 CART算法的原理与实现 - python3
			
本文来自<机器学习实战>(Peter Harrington)第九章"树回归"部分,代码使用python3.5,并在jupyter notebook环境中测试通过,推荐c ...
 - python字符串常用内置方法
			
python字符串常用内置方法 定义: 字符串是一个有序的字符的集合,用与存储和表示基本的文本信息. python中引号中间包含的就是字符串. # s1='hello world' # s2=&quo ...
 - iOS-OC、Swift 混编之桥接文件
			
新建一个OC语言的项目,然后添加一个基于NSObject的Swift文件SwiftFileModel类 .swift import UIKit class SwiftFileModel: NSObje ...
 - iOS-MD5加密、SHA1加密
			
1.MD5加密 ///MD5加密************************************** + (NSString *)md5:(NSString *)inputString{ co ...
 - 关于dom4j解析xml
			
一:相关jar包 dom4j-1.6.1.jar 二:用例xml文件 三:解析 注:可能有的小白不知道如果获取节点,so,you can: for (Iterator<Element> i ...
 - 使用json文件给es中导入数据
			
使用json文件可以给es中导入数据,10万条左右的数据可以一次导入,数量太大时导入就会报错.大数量的到导入还是需要用bulk方式. accounts.json文件格式如下: {"index ...
 - 济南清北学堂游记 Day  7.
			
完结撒花? 最后的模拟赛与讲题.大家似乎仍然乐在其中,虽然看评测结果,仍然是满地红. 其实到了最后已经是没有多少可写的了..... 一个精彩的地方是晚上填表的时候,群里炸锅了已经.到处都在刷CCL老师 ...
 - BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]
			
1444: [Jsoi2009]有趣的游戏 题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率 套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩 ...
 - BZOJ 1072: [SCOI2007]排列perm [DP 状压 排列组合]
			
题意:给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0) 100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15 看到整 ...
 - gitlab手动安装
			
[博客园 淡水的天空]] 老版 新版 Omnibus package installation Manually