日期:2014-05-16  浏览次数:20348 次

JavaScript学习笔记(十九) 柯里化(Curry)

柯里(Curry)

在接下来,我们会讨论的主题是柯里化(currying)和部分函数应用(partial function application),在我们深入这个主题之前,让我们
首先看看什么是部分函数用法。

函数应用(Function Application)

在一些纯函数编程语言中,一个函数不被描述为调用(called or invoked),而是应用(applied)。
在JavaScript中,我们有相同的情况——我们能应用(apply)一个函数通过Function.prototype.apply()方法,因为函数在JavaScript中实际上就是一个对象并且它们有自己的方法。
这里有个函数用法的例子:
// define a function
var sayHi = function (who) {
    return "Hello" + (who ? ", " + who : "") + "!";
};
// invoke a function
sayHi(); // "Hello"
sayHi('world'); // "Hello, world!"
// apply a function
sayHi.apply(null, ["hello"]); // "Hello, hello!"
正如你看到的,无论调用(invoking)一个函数或者应用(applying)一个函数,结果都是一样的。
 apply()接受两个参数:第一个是在函数中是绑定到this的对象;第二个参数是一个数组(包含多个参数),会成为在函数中可访问的类似数组(array-like)的arguments对象。
如果第一个参数是null,那么this将指向全局对象(global object),实际发生的就是当你调用的一个函数时,它不是一个具体对象的一个方法。

当一个函数是一个对象的方法,或者不传递null引用。
这里对象作为第一个参数传递给apply():
var alien = {
    sayHi: function (who) {
        return "Hello" + (who ? ", " + who : "") + "!";
    }
};
alien.sayHi('world'); // "Hello, world!"
sayHi.apply(alien, ["humans"]); // "Hello, humans!"
在这段代码中,在 sayHi()中this指向alien。在前一个例子中this指向的是全局对象(global object)。

正如这两个例子展示的,原来我们认为的调用一个函数不仅仅是语法糖,等同于函数应用。

注意,除apply()之外,还有一个Function.prototype.call()方法,但它仍然仅仅是apply()之上的一个语法糖。
有时,使用语法糖更好:当你有一个只接受一个参数的函数,你可以节约创建仅仅只有一个元素的数组的工作(call可以接受多个参数):
// the second is more efficient, saves an array
sayHi.apply(alien, ["humans"]); // "Hello, humans!"
sayHi.call(alien, "humans"); // "Hello, humans!"

部分函数应用(Partial Application)

现在我们知道调用一个函数实际上就是将一组参数应用于一个函数。
那么可以仅仅传递一些参数,而不是全部参数吗?如果你正在动手处理一个数学函数,这个其实和你经常做的非常类似

你有一个add()函数,将两个数相加:x 和 y,下面的代码片段展示你可以如何实现,给你的x=5,y=4:
// for illustration purposes
// not valid JavaScript
// we have this function
function add(x, y) {
    return x + y;
}
// and we know the arguments
add(5, 4);
// step 1 -- s