Dan*_*nce 47 javascript functional-programming partial-application promise
如何使用参数数组调用Function.prototype.bind,而不是硬编码参数?(不使用ECMA6,因此没有传播运营商).
我试图在使用回调的模块周围放置一个promises包装器,我想绑定传递给我的包装器方法的所有参数并绑定它们.然后我想用我自己的回调调用部分应用的绑定函数,它将解析或拒绝一个promise.
var find = function() {
var deferred, bound;
deferred = Q.defer();
bound = db.find.bind(null, arguments);
bound(function(err, docs) {
if(err) {
deferred.fail(err);
} else {
deferred.resolve(docs);
}
});
return deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)
但显然这不起作用,因为bind需要参数而不是参数数组.我知道我可以通过将我的回调插入到arguments数组的末尾并使用apply来做到这一点:
arguments[arguments.length] = function(err, docs) { ... }
db.find.apply(null, arguments);
Run Code Online (Sandbox Code Playgroud)
或者通过遍历arguments数组并为每个参数重新绑定函数:
var bound, context;
for(var i = 0; i < arguments.length; i++) {
context = bound ? bound : db.find;
bound = context.bind(null, arguments[i]);
}
bound(function(err, docs) { ... })
Run Code Online (Sandbox Code Playgroud)
但这两种方法都很脏.有任何想法吗?
Fel*_*ing 78
.bind是一个正常的功能,所以你可以调用.apply它.
您所要做的就是将原始函数作为第一个参数传递,将所需THIS变量作为参数数组中的第一个项传递:
bound = db.find.bind.apply(db.find, [null].concat(arguments));
// ^-----^ ^-----^ THIS
Run Code Online (Sandbox Code Playgroud)
是否可以认为更清洁是留给读者的.
Aad*_*hah 11
以下是我在所有项目中使用的常见代码片段:
var bind = Function.bind;
var call = Function.call;
var bindable = bind.bind(bind);
var callable = bindable(call);
Run Code Online (Sandbox Code Playgroud)
该bindable函数现在可用于传递数组,bind如下所示:
var bound = bindable(db.find, db).apply(null, arguments);
Run Code Online (Sandbox Code Playgroud)
实际上,您可以缓存bindable(db.find, db)以加快绑定速度,如下所示:
var findable = bindable(db.find, db);
var bound = findable.apply(null, arguments);
Run Code Online (Sandbox Code Playgroud)
您可以使用findable带或不带参数数组的函数:
var bound = findable(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
Felix的回答对我不起作用,因为arguments对象实际上并不是一个数组(正如Otts指出的那样).我的解决方案是简单地切换bind和apply:
bound = db.find.apply.bind(db.find, null, arguments);
Run Code Online (Sandbox Code Playgroud)