48

ハードコードされた引数ではなく、引数の配列を使用して Function.prototype.bind を呼び出すにはどうすればよいですか? (ECMA6 を使用していないため、スプレッド オペレーターはありません)。

コールバックを使用するモジュールの周りに promises ラッパーを配置しようとしています。ラッパー メソッドに渡されたすべての引数をバインドし、それらをバインドしたいと考えています。次に、プロミスを解決または拒否する独自のコールバックを使用して、部分的に適用されたバインドされた関数を呼び出したいと考えています。

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

しかし、 bind は引数の配列ではなく引数を期待しているため、明らかにこれは機能しません。引数配列の末尾にコールバックを挿入し、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) { ... })

しかし、これらの方法はどちらも汚いと感じます。何か案は?

4

11 に答える 11

11

以下は、すべてのプロジェクトで使用する一般的なコード スニペットです。

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

実際、次のようにキャッシュbindable(db.find, db)してバインドを高速化できます。

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

findableこの関数は、引数の配列の有無にかかわらず使用できます。

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

お役に立てれば。

于 2014-02-15T03:13:16.690 に答える
4

ES6 を使用している場合、Babel は次のようにコンパイルします。

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

に:

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

Babelはかなり決定的であると言っても過言ではないと思います。@lorenz-lo-sauer のおかげですが、ほとんど同じです。

于 2017-04-30T05:48:39.253 に答える
1

一般に、次のスキーマで十分です。

//obj = db
//fnName = 'find'
var args = [this||null].concat(Array.prototype.slice.apply(arguments);
obj[fnName].bind.apply(obj[fnName], args);
于 2015-02-05T12:17:55.520 に答える
1

あなたの例のように単純に引数配列にバインドし、関数にそれをそのまま配列bound()として扱わせてみませんか?

使用方法の外観からすると、関数を最終引数として に渡していますbound()。つまり、実引数配列を渡すことで、引数を 内のコールバックから分離する必要がなくなり、操作bound()が簡単になる可能性があります。

于 2014-02-02T05:35:54.713 に答える
1

以下は、受け入れられた回答よりもきれいだと思います

Function.bind.apply(db.find, [null].concat(arguments));
于 2016-11-17T12:19:11.117 に答える
0

決定的で簡単な答えは

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

つかむのはちょっと「難しい」ですが、きちんとしています。

于 2016-11-25T09:25:55.253 に答える