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 ...
随机推荐
- java对象引用-要掌握的细节2
目的:加深对java引用变量的理解,避免数据的处理的偏差. 问题: 1.一个集合List ,将新建Student对象stu放入List之后,再给stu的成员变量例如id,name赋值.此时List中的 ...
- OpenStreetMap数据清洗(SQL&MonogoDB版本)
目标:通过网上下载的OpenStreetMap.xml数据格式,将该文件的格式进行统计,清洗,并导出成CSV格式的文件,最后倒入到SQLite中 本案例中所需的包 import csv import ...
- SQLServer2008修改sa密码的方法与SQL server 2008数据库的备份与还原
sa密码的修改转载自:http://blog.csdn.net/templar1000/article/details/20211191 SQL server 2008数据库的备份与还原转自 :htt ...
- 浏览器中页面的visibility状态及变化监听
需求 在浏览器中播放视频,当用户进行页面切换操作时.需要根据视频播放页是否处于可见状态,来控制视频的暂停及重新播放. 相关文档 参考MDN中,关于页面的可见性相关的API说明.https://deve ...
- centos 6.3安装ssh
centos 6.3安装ssh 安装ssh服务器端软件 yum install openssh-server 安装ssh客户端软件 yum install openssh-clients ...
- ABP官方文档翻译 3.2 值对象
值对象 介绍 值对象基类 最佳实践 介绍 "展现领域描述性层面且没有概念性身份的对象称之为值对象."(Eric Evans). 和实体相反,实体有身份标示(Id),值对象没有身份标 ...
- DG环境的日常巡检
DG环境的日常巡检 目录 1.DG环境的日常巡检4 1.1.主库环境检查4 1.1.1.主库实例启动状态检查4 1.1.2.主库启动模式检查4 1.1.3.主库DG环境的保护模式检查4 1.1.4.主 ...
- [一个脑洞] Candy?'s 不饱和度
update 2017.7.10 Candy?'s 不饱和度 题目背景 化学老师让同学们出题!昌老师担任有机组组长! Candy?出了一道数不饱和度的题目,昌老师不会做所以拒绝接受!!! 于是Cand ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
- 安装Spring Tool Suite(STS)
JAVA开发工具中,常用工具就是Eclipse,IntelliJ IDEA. 现在使用spring boot&cloud框架进行开发的时候,虽然可以使用上面两个工具,但都未必就真的量身定制,I ...