1

出典: 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)));
4

2 に答える 2

7

そうしないと、バインドされた関数からの戻り値が失われるため、2 番目の戻り値が必要です。

あなたはすでにこれを知っているかもしれませんが、言及しても害はありません。別の関数内にラップしない場合は、実行コンテキスト (関数内で参照する必要があるもの)を設定することのみが想定されており、それを呼び出さないため、次善fn.applyの関数を直接呼び出すことになります。fnbindthis

callJavascript メソッドは、メソッドまたはメソッドを呼び出すことで呼び出すことができますapply。以下に小さな例を示します。

function example() {
    alert("useless example");
}

example.apply() // or example.call(), alerts "useless example";

Prototype の bind() の外側の関数は、バインドされた関数の目に見えないラッパーのように機能するはずです。したがって、ラッパーに渡されるすべての引数は、バインドされた関数にも渡される必要があり、バインドされた関数が返す値を返す必要があります。これが return ステートメントが存在する理由です。

fn.apply 内で args.concat を実行する理由は異なり、オプションではありません。bindin Prototype を使用すると、バインドされた関数の先頭に引数を追加できます。

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
于 2010-04-21T10:51:55.563 に答える
0

古い投稿ですが、新しいアプローチです;)

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) の実行の console.log に引数が表示されなくなっていることがわかります。これは、引数オブジェクトがすべての関数内のローカル変数であるためです。 少しややこしいかもしれませんが、基本的には次のことを意味します。

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

[].slice.call を使用して配列に変換できる特別な引数 object = {0:4,1:5,2:6} を使用します。ここで、arguments はローカル オブジェクトであり、呼び出し中に自動的に割り当てられます。関数。

于 2015-05-25T13:45:21.127 に答える