您的位置:首页 > Web前端 > JavaScript

对Javascript柯里化currying的理解

2015-03-15 12:32 435 查看

1. 学习currying

对于currying,在《Javascript高级程序设计(第3版)》的604页第22.1.5节有一句言简意赅的解释:“它用于创建已经设置好了一个或多个参数的函数”。要更好的学习和理解currying,建议阅读以下几篇博文:

JS中的柯里化(currying) —— 张鑫旭

javascript的currying函数 —— 司徒正美

Javascript中currying的实现 —— Aaron

如果要我自己写,最多也就是对以上几篇的重复,所以理论部分不再赘述,下面讲讲我的理解。

2. 使用currying

市面上有很多currying的实现,实际上达成的效果都一致:我们有一个函数fn,通过currying(fn[, arg1][, arg2][, ...][, argn]),将fn包装为前n个参数固定的新函数,这里的n为currying中的arg数。

在看currying的时候,大家最爱用add函数的例子(参见1中建议阅读的几篇博文):

function add(x, y) {
return x + y;
}

通过以下方式可以固定add的第一个参数,产生从addZero到addNine的函数(先忽略掉currying及其注释说明,看currying对add产生的效果,这里主要看for(var key in dict)循环里的注释):

function gener() {
var currying = function(fn) {
// fn 要进行柯里化的函数
// args 固定下来的参数,可以多个
var args = [].slice.call(arguments, 1);
// 包装fn,里面的arguments是向包装后的fn传入的未固定参数,args已固定参数
return function() {
// 已经固化的参数args和新传入的参数arguments连接成新参数数组newArgs
var newArgs = args.concat([].slice.call(arguments));
// 包装原fn并返回,参数为newArgs,apply(null, [...])方便直接用数组参数newArgs调fn
return fn.apply(null, newArgs);
};
};

function add(a, b) {
return a + b;
}

var dict = {
addNine: 9, addEight: 8, addSeven: 7, addSix: 6, addFive: 5,
addFour: 4, addThree: 3, addTwo: 2, addOne: 1, addZero: 0
};
for(var key in dict) {
// 相当于执行(this是window):
// this.addNine = cuurying(add, 9)
// this.addEight = cuurying(add, 8)
// ...
// this.addZero = cuurying(add, 0)
// 其中,addNine是固化add的第一个参数为9的函数,其他同理
this[key] = currying(add, dict[key]);
}

}

gener();

console.log(['addZero(1): ' , addZero(1)].join('') );
console.log(['addOne(1): ' , addOne(1)].join('') );
console.log(['addTwo(1): ' , addTwo(1)].join('') );
console.log(['addThree(1): ', addThree(1)].join(''));
console.log(['addFour(1): ' , addFour(1)].join('') );
console.log(['addFive(1): ' , addFive(1)].join('') );
console.log(['addSix(1): ' , addSix(1)].join('') );
console.log(['addSeven(1): ', addSeven(1)].join(''));
console.log(['addEight(1): ', addEight(1)].join(''));
console.log(['addNine(1): ' , addNine(1)].join('') );
控制台输出:



上面代码中使用的currying函数如下(注释写得不好,希望能帮助理解,这里将上面的currying函数提出来放这里,它是实现柯里化的关键):

var currying = function(fn) {
// fn 要进行柯里化的函数
// args 固定下来的参数,可以多个
var args = [].slice.call(arguments, 1);
// 包装fn,里面的arguments是向包装后的fn传入的未固定参数,args已固定参数
return function() {
// 已经固化的参数args和新传入的参数arguments连接成新参数数组newArgs
var newArgs = args
4000
.concat([].slice.call(arguments));
// 包装原fn并返回,参数为newArgs<span style="font-family: Arial, Helvetica, sans-serif;">,apply(null, [...])方便直接用数组参数newArgs调fn</span>
return fn.apply(null, newArgs);
};
};

说明都写在注释中了,如果理解困难,可以参考第1部分中的几篇博文。大家可能还不知道柯里化的作用,可以查看张鑫旭的《JS中的柯里化(currying)》中的第二部分“柯里化有什么作用?”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息