使用Function.prototype.bind与参数数组?

我怎样才能调用Function.prototype.bind一个参数数组,而不是硬编码参数? (不使用ECMA6,所以没有传播运营商)。

我试图把承诺包装周围使用callback模块,我想绑定所有parameter passing到我的包装方法,并绑定它们。 然后我想用我自己的callback调用部分应用的绑定函数,这将解决或拒绝承诺。

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; } 

但是显然这不起作用,因为绑定需要参数而不是参数数组。 我知道我可以通过将我的callback插入到参数数组的末尾来使用apply:

 arguments[arguments.length] = function(err, docs) { ... } db.find.apply(null, 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) { ... }) 

但是这两种方法都很脏。 有任何想法吗?

.bind是一个正常的函数,所以你可以调用.apply
您所要做的就是将原始函数作为第一个参数,并将所需的THISvariables作为参数数组中的第一项:

 bound = db.find.bind.apply(db.find, [null].concat(arguments)); // ^-----^ ^-----^ THIS 

是否可以认为是清洁的是留给读者的。

以下是我在所有项目中使用的常见代码片段:

 var bind = Function.bind; var call = Function.call; var bindable = bind.bind(bind); var callable = bindable(call); 

bindable函数现在可以用来传递一个数组来bind ,如下所示:

 var bound = bindable(db.find, db).apply(null, arguments); 

实际上你可以cachingbindable(db.find, db)来加速绑定,如下所示:

 var findable = bindable(db.find, db); var bound = findable.apply(null, arguments); 

您可以使用带或不带参数数组的findable函数:

 var bound = findable(1, 2, 3); 

希望这可以帮助。

Felix的答案对我来说不起作用,因为arguments对象不是真正的数组(如Otts指出的那样)。 我的解决scheme是简单地切换bindapply

 bound = db.find.apply.bind(db.find, null, arguments); 

为什么不按照你的例子简单地绑定到参数数组,并且让bound()函数把它当作数组来对待呢?

通过看你的用法,然后你传递一个函数作为bound()的最后一个参数,这意味着通过传递实际的参数数组,你可以避免在bound()分离参数和callback,和玩。

一般来说,这个模式就足够了:

 //obj = db //fnName = 'find' var args = [this||null].concat(Array.prototype.slice.apply(arguments); obj[fnName].bind.apply(obj[fnName], args); 

我发现比接受的答案更清洁

 Function.bind.apply(db.find, [null].concat(arguments)); 

如果有人正在寻找抽象样本:

 var binded = hello.apply.bind(hello,null,['hello','world']); binded(); function hello(a,b){ console.log(this); //null console.log(a); //hello console.log(b); //world } 

只是有一个替代的想法,部分应用上下文的null值,然后使用apply来调用部分应用函数。

 bound = db.find.bind.bind(null).apply(null, arguments); 

这在@ Felix的答案中删除了对稍微幽灵般的[null].concat()的需求。

一个明确而简单的答案可能是

 Function.apply.bind(this.method, this, arguments); 

有点“难”把握,但整齐。

对于那些使用ES6的人来说,Babel编译:

 db.find.bind(this, ...arguments) 

至:

 db.find.bind.apply(db.find, [this].concat(Array.prototype.slice.call(arguments))); 

我觉得说巴别是非常明确的。 信用@洛伦兹洛绍尔,但它几乎是相同的。