本文翻译自《Secrets_of_the_JavaScript_Ninja》 本文由小豪翻译
之前在交流会上,和杜欢讨论过闭包的一些小东西,这里的文章主要还是从闭包产生的结果切人,讲述闭包的一些妙用,不探讨闭包产生的原因
函数参数的嵌入技术,原文是"Partially Applying Functions",是一种在函数执行前,对其增加参数的方法。事实上,这个方法让你调用了一个新的函数。
注:assert是qunit单元测试所用的方法,第一个参数若为true则输出第二个参数,通常true表示执行结果为预期的值,下面都用到了assert对结果进行校验
String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = ("John, Resig, Boston").csv();
assert( results[1] == "Resig", "字母切分成功" );
partial方法就是能够实现partially apply的函数,我们可以看到虽然csv在调用的时候没有带任何参数,但是还是按照/,\s*/进行split了。
prototype框架里有一个curry函数,和partial比较类似。
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变量和args变量保存下来,并可以让返回的函数能够访问到,在返回的函数中,我们将本身的参数和保存下的args参数进行合并,也就做到了嵌入参数的功能。
curry函数看起来很妙,但是我们还可以做的更好。如果我们需要将一些参数保留给可能传入的函数,那么就需要做一些更多的处理。
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);
};
};
我们通过将预设参数中的undefine值替换为传入的函数,从而实现了一个更方便的参数嵌入函数。看几个实用的例子。
//delay函数的实现
var delay = setTimeout.partial(undefined, 10);
delay(function(){
assert( true, "函数延迟调用成功" );
});
//事件绑定的实现
var bindClick = document.body.addEventListener
.partial("click", undefined, false);
bindClick(function(){
assert( true, "当前函数绑定了click事件" );
});
这个技术的主要目的函数缩小代码的复杂度,让API的使用更加方便清晰。
对闭包的产生和原理感兴趣的同学,可以看下http://www.otakustay.com/closure-ppt/。
扫码关注w3ctech微信公众号
共收到0条回复