使用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
。
您所要做的就是将原始函数作为第一个参数,并将所需的THIS
variables作为参数数组中的第一项:
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是简单地切换bind
和apply
:
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)));
我觉得说巴别是非常明确的。 信用@洛伦兹洛绍尔,但它几乎是相同的。