JavaScript函数柯里化
函数式
JavaScript是以函数为一等公民的函数式语言。函数在JavaScript中也是一个对象(继承制Function),函数也可以作为参数传递成函数变量。最近几年函数式也因为其无副作用的特性、透明性、惰性计算等在高并发,大数据领域火起来了。
JavaScript中也有如Underscore、lodash之类的函数式库,如lodash的使用方式:
var names = _.chain(users)
.map(function(user){
return user.user;
})
.join(" , ")
.value();
console.log(names);
关于lodash更多内容请参考JavaScript工具库之Lodash.
柯里化
今天文章将以高阶函数中的柯里化方式来,看看JavaScript的函数式能力。
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
在理论计算机科学中,柯里化提供了在简单的理论模型中比如只接受一个单一参数的lambda 演算中研究带有多个参数的函数的方式。
JavaScript的柯里化实现
下边的例子,我们将把柯里化方式泛化为接受任意个参数,直到声明的方法参数个数饱和才执行,所以根据参数个数可以有多种柯里化函数产生。
代码如下:
(function(global) {
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m,
FN_ARG_SPLIT = /,/,
FN_ARG = /^\s*(_?)(\S+?)\1\s*$/,
STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var getArgLength = function(func) {
var fnText = func.toString().replace(STRIP_COMMENTS, '');
var argDecl = fnText.match(FN_ARGS);
var params = [];
argDecl[1].split(FN_ARG_SPLIT).forEach(function(arg) {
arg.replace(FN_ARG, function(all, underscore, name) {
params.push(name);
});
});
return params.length;
};
var curryFunc = function(func, len) {
len = len || getArgLength(func);
var args = [];
if (len === 0) {
return func.apply(null);
}
return function() {
[].push.apply(args, [].slice.apply(arguments));
if (args.length >= len) {
return func.apply(null, args);
}
return arguments.callee;
};
};
global.curryFunc = curryFunc;
})(this);
function add(x, y, z) {
return x + y + z;
}
console.log("result 1:", curryFunc(add)(1, 2)(3));
console.log("result 2:", curryFunc(add)(1)(2, 3));
console.log("result 3:", curryFunc(add)(1)(3)(2));
function add(x, y, z) {
return x * y * z;
}
console.log("result 1:", curryFunc(add)(2, 4)(6));
console.log("result 2:", curryFunc(add)(2)(4, 6));
console.log("result 3:", curryFunc(add)(2)(6)(4));
function sayHello() {
return "hello";
}
console.log(curryFunc(sayHello));
首先上面会利用正则来获取传入函数的参数个数。再返回一个函数的代理,每次的调用都会将传入参数缓存在args临时变量中,直到参数个数饱和才会立即执行。代码比较冗长,慢慢品味,当然有不足之处,也希望大家指出来。
JavaScript函数柯里化的更多相关文章
- Javascript函数柯里化(curry)
函数柯里化currying,是函数式编程非常重要的一个标志.它的实现需要满足以下条件,首先就是函数可以作为参数进行传递,然后就是函数可以作为返回值return出去.我们依靠这个特性编写很多优雅酷炫的代 ...
- JavaScript函数柯里化的一些思考
1. 高阶函数的坑 在学习柯里化之前,我们首先来看下面一段代码: var f1 = function(x){ return f(x); }; f1(x); 很多同学都能看出来,这些写是非常傻的,因为函 ...
- javascript函数柯里化初探
// 柯里化之前 function add(x,y,z){ return x+y+z; } add(1,2,3) // 6 // 柯里化之后 function curryAdd(x){ return ...
- 深入理解javascript函数进阶系列第二篇——函数柯里化
前面的话 函数柯里化currying的概念最早由俄国数学家Moses Schönfinkel发明,而后由著名的数理逻辑学家Haskell Curry将其丰富和发展,currying由此得名.本文将详细 ...
- 简单粗暴详细讲解javascript实现函数柯里化与反柯里化
函数柯里化(黑人问号脸)???Currying(黑人问号脸)???妥妥的中式翻译既视感:下面来一起看看究竟什么是函数柯里化: 维基百科的解释是:把接收多个参数的函数变换成接收一个单一参数(最初函数的第 ...
- JavaScript中的事件循环机制跟函数柯里化
一.事件循环机制的理解 test();//按秒输出5个5 function test() { for (var i = 0; i < 5; i++) { setTimeout(() => ...
- 一道javascript面试题(闭包与函数柯里化)
要求写一个函数add(),分别实现能如下效果: (1)console.log(add(1)(2)(3)(4)()); (2)console.log(add(1,2)(3,4)()); (3)conso ...
- 精读JavaScript模式(六),Memoization模式与函数柯里化的应用
假期就这么结束了!十天假就有三天在路上,真的难受!想想假期除了看了两场电影貌似也没做什么深刻印象的事情.流浪地球,特效还是很赞,不过对于感情的描写还是逃不掉拖沓和尴尬的通病,对于国产科幻还是抱有支持的 ...
- JavaScript之函数柯里化
什么是柯里化(currying)? 维基百科中的解释是:柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术.意思就是当函 ...
随机推荐
- Python list列表的排序
当我们从数据库中获取一写数据后,一般对于列表的排序是经常会遇到的问题,今天总结一下python对于列表list排序的常用方法: 第一种:内建函数sort() 这个应该是我们使用最多的也是最简单的排序函 ...
- php内核探索 [转]
PHP内核探索:从SAPI接口开始 PHP内核探索:一次请求的开始与结束 PHP内核探索:一次请求生命周期 PHP内核探索:单进程SAPI生命周期 PHP内核探索:多进程/线程的SAPI生命周期 PH ...
- nodejs的url参数获取
express封装了多种http请求方式,我们主要使用get和post两种,即qpp.get和qpp.post.qpp.get和qpp.post的第一个参数都为请求的路径,第二个参数为处理请求的回调函 ...
- javascript实现字符串的截取
截取字符串方法有很多的,(不含根据传入参数截取成数组的split()方法)这里说的是子字符串,所以不说split()方法了. slice(),substr(),substring()一共三种方法,其中 ...
- 省市二级联动(原生JS)
代码如下: <html> <head> <meta charset="UTF-8"> <title>省市二级联动</title ...
- myeclipse如何修改Web项目名称,eclipse如何修改项目名字
myeclipse如何修改Web项目名称 1.复制一个现有的项目,重命名项目名称 2.这里的项目名称重新命名了,但是Web项目本质下的名称还是没有改变的.所以需要更改,更改方法-->选择项目右击 ...
- Eclipse JAVA项目的 目录结构 和 导入
说明:本文所有测试以java工程为例: 1. Eclipse下的java工程目录 eclipse的基本工程目录叫做workspace,每个运行时的eclipse实例只能对应一个workspace,也就 ...
- php面向对象学习
近期跟着别人开发一套php程序,深感自己面向对象很白痴,于是再次巩固了一下面向对象的学习,自己整理了一下这几天面向对象的东西,给大家分享!! 面向对象的三大特性: 封装 -- 隐藏内部实现,稳定外部接 ...
- Spring笔记--0907
包含ioc和aop两大核心概念 aop----事务管理 spring框架运用的设计模式(查一下) ---------------------------------------Ioc(控制反转)和Di ...
- WIN8 平台应用隐私声明
隐私权声明 本应用连接网络仅为控制硬件设备,不会收集你的个人信息,也不共享你个个人信息. 应用名称 雅典娜监控平台移动客户端 关于本应用 本应仅为控制设备应用,不关注任何配置相关信息,所有数据均来自服 ...