f是一个普通函数,接受两个参数,并返回他们相加的结果
function f(x, y) {
return x + y
}
g是一个柯里化函数,接受一个参数,返回一个新的函数
function g(x) {
return function(y) {
return x + y
}
}
传统函数调用是接收多个参数返回一个值,而柯里化函数则是接收参数返回新的函数,新的函数又可以接受参数再返回新的函数,直至最后返回结果值使用柯里化函数的优势是我们可以”部分应用”(Partial Application)函数的参数,生成新的函数,这在函数编程中是至关重要的
g(1)(2) == 3
var add1 = g(1)
add1(100) == 101
var add100 = g(100)
add100(100) == 200
现在我们来分析上面的问题。
首先,add(1) == 1,说明add函数应该返回一个整数。但是add(1)(2) == 3表明毫无疑问add(1)返回的值应该是一个函数。所以现在我们的问题就变成了,有没有可能让一个函数等于一个整数呢?(注意比较操作符是松散的==,而不是严格===。
答案是有可能的。这里需要我们了解JS的一个小知识。那就是valueOf属性。当我们将一个对象和一个primitive进行比较的时候,JS会调用对象的valueOf方法获取一个primitive值,然后在进行比较。
var a = {}
a.valueOf = function(){ return “hello world!” }
a == “hello world!” // true
a === “hello world!” // false,严格等于操作符会比较数据类型
从这里就可以看出,只要我们定义了对象a的valueOf方法,我们可以让他和任意的primite值相等。
函数也是一个对象。所以这个问题的解决方法就很清楚了。每次返回的都是一个函数。这个函数的valueOf会返回传入参数的和。
大家可以试试看自己实现,下面是我的实现~
1 | function total(args) { return [].slice.call(args).reduce((t, c) => t + c, 0) } function add() { function factor(value) { var result = function(){ return factor(value + total(arguments)) } result.value = value result.valueOf = function(){ return this.value } return result } return factor(total(arguments)) } |