文章目录
  1. 1. 偏应用函数

偏应用函数

“分部应用”一个函数是一项特别有趣的技术,在函数调用之前,我们可以预先传入一些函数。实际上,偏应用函数返回了一个含有预处理参数的新函数,以便后期可以调用。
这类代理函数--代理的是另外一个函数,并且在执行的时候会调用所代理的函数。
这种在一个函数中首先填充几个参数(然后再返回一个新函数)的技术称之为柯里化(curring)。

柯里化函数示例(在第一个特定参数中进行填充)

1
2
3
4
5
6
7
8
9
Function.prototype.curry = function() {
//该函数以及预填充的参数是保存在闭包中的
var fn = this,
args = Array.prototype.slice.call(arguments);
//创建一个匿名柯里化函数
return function(){
return fn.apply(this,args.concat(Array.prototype.slice.call(arguments)));
};
}

这种技术是另外一个利用闭包记住状态的很好例子。在本例中,我们要记住新增加的函数(这里的this参数不会存在于任何闭包中,因为每个函数调用的时候都有自己的this)以及预填充参数,并将它们转移到新创建的函数中。该新函数将有预填充的参数以及刚传入的新参数。其结果就是,这样的方法可以让我们预先传入一些参数,然后返回给我们一个新的简单函数供我们使用。

虽然这种风格的分部函数非常有用,但我们可以做的更好。如果我们给特定函数传递遗漏的参数,而不是从参数列表一开始就传。

一个更复杂的”分部”函数

1
2
3
4
5
6
7
8
9
10
11
12
Function.prototype.partial = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function(){
var arg = 0;
for (var i=0; i < args.length && arg < arguments.length; i++) {
if (args[i] === undefined) {
args[i] = arguments[arg++];
}
}
return fn.apply(this, args);
};
}

该实现的本质类似于Prototype的curry()方法,但它有几个重要的差异。值得注意的是,用户可以在参数列表的任意位置指定参数,然后在后续的调用中,根据遗漏的参数值是否等于undefined来判断参数的遗漏,要实现这种功能,我们添加了参数合并功能。很有效果,遍历传入的所有参数参数,判断相应的参数是否遗漏了(是否是undefined),然后沿着顺序填充遗漏的参数。

1
2
3
4
5
var delay = setTimeout.partial(undefined, 10);
delay(function(){
assert(true, "A call to this function will be delayed 10 ms.");
});

这段代码创建了一个新的函数,名为delay(),通过该函数,我们可以传入另外一个10毫秒后进行调用的异步函数。
我们也可以创建一个简单的函数用于事件绑定:

1
2
3
4
5
var bindClick = document.body.addEventListener.partial("click", undefined, false);
bindClick(function(){
assert(true, "Click event bound via curried function");
});
文章目录
  1. 1. 偏应用函数