プロトタイプ。JS関数バインディングコードの説明
-
30-09-2019 - |
質問
から: http://ejohn.org/apps/learn/#2
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
};
2回目のリターンが必要な理由(fn.applyの前)を教えてもらえますか?
また、誰もがなぜargs.concatが必要なのかを説明できますか?なぜそれは書き直さないのでしょうか:
fn.apply(object, args)
それ以外の
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
解決
それ以外の場合は、バインドされた関数からの返品値が失われるため、2番目のリターンが必要です。
あなたはすでにこれを知っているかもしれませんが、言うまでもなく害はありません。ラップしない場合 fn.apply
別の関数の中で、私たちは関数を直接呼び出しています fn
これは、次の最適です bind
実行コンテキストを設定することになっているだけです(何がすべきか this
関数内を参照してください)、それを呼び出しません。
JavaScriptメソッドは、電話をかけることで呼び出すことができます call
また apply
それらの方法。ここに小さな例があります:
function example() {
alert("useless example");
}
example.apply() // or example.call(), alerts "useless example";
プロトタイプのbind()の外部関数は、バインドされた関数の周りの目に見えないラッパーのように機能するはずです。したがって、ラッパーに渡される引数もバインドされた関数に渡される必要があり、バインドされた関数が返す値を返す必要があります。そのため、returnステートメントがあります。
fn.apply内でargs.concatを実行する理由は異なり、オプションではありません。 bind
プロトタイプでは、バインドされた関数に引数を準備できます。
args
私たちが呼んだときに渡された議論を表します bind
関数について。 arguments
結合関数と呼ばれるときに渡された引数を表します。基本的に2つの配列を連結しています。
上記の例から:
var obj = { x: 'prop x' };
var boundExample = example.bind(obj, 12, 23); // args => 12, 23
boundExample(36, 49); // arguments => 36, 49
// arguments that our example() function receives => 12, 23, 36, 49
他のヒント
古い投稿ですが、新しいアプローチ;)
Function.prototype.bind = function(){
var fn = this,
context = arguments[0],
args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args.concat([].slice.call(arguments)));
}
}
obj = {'abc':'x'};
var func = function() {
console.log(arguments);
alert(this.abc);
}
var x = func.bind(obj);
console.log(x(1,2,3));
これは説明するのに非常に良い例です。実行して、コンソールログを確認します。次に、コードを変更して除外します
[].slice.call(arguments)
X(1,2,3)の実行のコンソール。ログがもう引数を表示していないことがわかります。 これは、引数オブジェクトがすべての関数内のローカル変数であるためです。 それは少し混乱するかもしれませんが、それが意味するのは基本的に:
var x = func.bind(obj,1,2,3);
この関数を内部的に返します:
function() {
return fn.apply(obj, [1,2,3].concat([].slice.call(arguments)));
}
したがって、それは関数のテンプレートのようなものです。
あなたが今それを実行するとき:
x(4,5,6)
これは実行されます:
fn.apply(obj, [1,2,3].concat([].slice.call(arguments)))
特別な引数を使用してobject = {0:4,1:5,2:6}。[] .slice.callを使用して配列に変換できます。関数。