当使用高阶函数时,我希望我的函数不要对它作为参数接收的回调做出任何假设。一般来说,代码越松耦合越好。
例如,假设我为 编写了一个高阶函数forEach
:
function forEach(array, callback, that) { // that is optional
var length = array.length;
for (var i = 0; i < length; i++)
callback.call(that, array[i], i); // pass the value and the index
}
现在说我想使用它:
Array.prototype.double = function () {
forEach(this, function (value, index) {
this[index] = 2 * value;
}); // oops, I forgot that
};
var array = [1, 2, 3];
array.double();
上面的代码会导致变量泄漏到全局范围内。不是什么好事。在此处查看演示:http: //jsfiddle.net/8dad4/
有什么选择?删除可选的第三个参数并使用闭包:
function forEach(array, callback) {
var length = array.length;
for (var i = 0; i < length; i++)
callback(array[i], i);
}
不仅代码更小,而且不会出现任何意外的全局泄漏(除非您像白痴一样使用this
而不是外部)。that
让我们看一个例子:
Array.prototype.double = function () {
var that = this;
forEach(this, function (value, index) {
that[index] = 2 * value;
});
};
var array = [1, 2, 3];
array.double();
演示在这里:http: //jsfiddle.net/8dad4/1/
嗯......这似乎不是很诱人 - 我不想创建一个新变量。我们可以做得更好吗?是的,我们当然可以。这是我比较喜欢的方法(我们还是用第二个forEach
函数):
Array.prototype.double = function () {
forEach(this, function (value, index) {
this[index] = 2 * value;
}.bind(this));
};
var array = [1, 2, 3];
array.double();
演示在这里:http: //jsfiddle.net/8dad4/2/
哇,这不是更好吗?我们结合了方法一和方法二。好处:
- 该
forEach
函数不假设任何内容。代码更松散耦合。
- 我们不需要像
that
. 不需要关闭。
- 对于正在发生的事情没有任何困惑。
我们可以这样做,因为传递给的匿名函数forEach
是一个函数表达式。所以我们只是追加.bind(this)
它,我们就完成了。