Frage

Von: 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)));
  };
};

Kann mir jemand sagen, warum die zweite Rückkehr notwendig ist (vor fn.apply)?

Auch kann jemand erklären, warum args.concat notwendig ist? Warum sollte es nicht neu geschrieben werden als:

fn.apply(object, args)

statt

return fn.apply(object,
          args.concat(Array.prototype.slice.call(arguments)));
War es hilfreich?

Lösung

Die zweite Rückkehr ist notwendig, weil sonst werden wir alle Rückgabewert von der gebundenen Funktion verlieren.

Sie können bereits wissen, aber nicht zu erwähnen verletzt. Wenn wir in einer anderen Funktion nicht fn.apply wickeln, dann sind wir direkt die Funktion fn Aufruf, die suboptimale ist, als bind nur den Ausführungskontext festlegen soll (was soll innerhalb der Funktion beziehen sich auf this) und nicht invoke es .

Javascript Methoden können durch den Aufruf der call oder apply Methode auf sie aufgerufen werden. Hier ist ein kleines Beispiel:

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

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

Die äußere Funktion in Prototype bind () soll an die Arbeit wie eine unsichtbare Wrapper um die gebundene Funktion. Damit alle Argumente, die an den Wrapper übergeben werden sollen auch an die gebundenen Funktion übergeben werden, und es muss einen Wert zurückgeben, dass die gebundene Funktion zurückkehrt, weshalb die return-Anweisung gibt.

Der Grund dafür args.concat innen fn.apply anders ist und es ist nicht optional. bind in Prototype können Sie Argumente an die gebundenen Funktion vorangestellt wird.

args stellt die Argumente, die übergeben wurden, als wir bind auf die Funktion aufgerufen. arguments stellt die Argumente, die übergeben wurden, als wir die gebundene Funktion aufgerufen. Wir sind im Grunde verketten zwei Arrays gibt.

Aus dem obigen Beispiel:

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

Andere Tipps

Alte Post, aber ein neuerer Ansatz;)

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

Dies ist ein sehr gutes Beispiel zu erklären. Führen Sie es und überprüfen Sie das Konsolenprotokoll. Dann ändern Sie den Code auszulassen

[].slice.call(arguments)

Sie werden sehen, dass die console.log der Ausführung von x (1,2,3) ist mehr die Argumente nicht angezeigt. Das ist, weil die Argumente Objekte ist eine lokale Variable in allen Funktionen. Das mag ein wenig verwirrend klingen, aber was es bedeutet, ist im Grunde:

var x = func.bind(obj,1,2,3);

Gibt diese Funktion intern:

function() {
    return fn.apply(obj, [1,2,3].concat([].slice.call(arguments)));
}

So ist es eher eine Vorlage für die Funktion ist.

Wenn Sie laufen jetzt ist es wie:

x(4,5,6)

Dies wird RAN:

fn.apply(obj, [1,2,3].concat([].slice.call(arguments)))

mit einem speziellen Argumente Object = {0: 4,1: 5,2: 6}, die in eine Anordnung überführt werden kann unter Verwendung von [] .slice.call wo Argumente ist ein lokales Objekt, das automatisch während der Invokation der Funktion zugeordnet ist beeing.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top