2014-02-28 11 views
10

Da bind kein Cross-Browser ist (alte) Funktion gibt es eine polyfill dafür: (von John Resig Buch)Javascript Bind Implementierung?

/*1*/  Function.prototype.bind = function() 
/*2*/  { 
/*3*/   var fn = this, 
/*4*/    args = Array.prototype.slice.call(arguments), 
/*5*/    object = args.shift(); 
/*6*/   return function() 
/*7*/   { 
/*8*/    return fn.apply(object, 
/*9*/     args.concat(Array.prototype.slice.call(arguments))); 
/*10*/   }; 
/*11*/  }; 

Aber ich verstehe nicht, warum wir arguments brauchen in Zeile #9.

ich meine:

Wenn ich dieses Objekt:

var foo = { 
    x: 3 
} 

Und ich habe diese Funktion:

var bar = function(p,b){ 

    console.log(this.x+'  '+p+' '+b); 
} 

Also, wenn ich bar will im foo Kontext laufen, mit Parametern - Alles, was ich tun muss, ist:

var boundFunc = bar.bind(foo,1,2) 
boundFunc()... 

Also wenn ich rufe var.bind(foo,1,2) die arguments ist [object Object],1,2.

Diese Argumente werden in Zeile 4 gespeichert.

Großartig.

Nun wird die bind Funktion liefert seine eigene closured Funktion:

function() 
    { 
     return fn.apply(object, 
      args.concat(Array.prototype.slice.call(arguments))); 
    } 

Frage

Warum wir arguments hier brauchen? es scheint, dass sie für etwas wie sind:

var boundFunc = bar.bind(foo,1,2) 
boundFunc (more1,more2....) //<----- ?? 

Fehle ich etwas?

Oonce ich setze die erste var boundFunc = bar.bind(foo,1,2), ich habe bereits die Parameter deklariert. Warum brauchen wir sie zweimal?

Antwort

13

Es gibt zwei Orte, die Sie in Argumente an die gebundenen Funktion übergeben können:

1) Wenn Sie binden nennen (die erste arguments). Diese werden beim Aufruf immer auf die gebundene Funktion angewendet.

2) Wenn Sie die gebundene Funktion aufrufen (die zweite arguments). Dies sind die "more1, more2", die Sie erwähnen. Diese Änderungen hängen davon ab, was beim Aufruf des gebundenen Arguments bereitgestellt wird.

Zeile 9 kombiniert die ursprünglichen gebundenen Argumente mit den angegebenen zusätzlichen Argumenten.

Ich denke, das Konzept, das Sie möglicherweise verwirrt werden, ist, dass Sie nicht alle Argumente anfänglich binden müssen - Sie können nur das Kontextobjekt binden, oder Sie können auch das erste Argument binden, aber Aufrufer des gebundenen haben Funktion liefert den Rest.Zum Beispiel:

function sum() { 
var _sum = 0 
for (var i = 0; i < arguments.length ; i++) { 
    _sum += arguments[i]; 
} 
return _sum; 
} 
var sum_plus_two = sum.bind({},2); 
sum_plus_two(5,7) == 14; 
+2

Ich denke, ein Beispiel wird nur die klare Antwort hinzufügen =) – Prusse

+0

gut gemacht. . . . . . ... –

4

.bind dient auch als partial application Lösung. Event-Handler könnten das beste Beispiel sein:

var handler = function(data, event) { }; 

element.addEventListener('click', handler.bind(null, someData)); 

Wenn die Argumente von dem eigentlichen Funktionsaufruf nicht weitergegeben werden würden, könnten Sie nicht das Ereignisobjekt zugreifen.

+0

Event ist die erste imho –

+0

Aber wir haben bereits einen Wert als erstes Argument ('someData') gebunden. Wenn also der Event-Handler aufgerufen wird und das Event-Objekt übergeben wird, wird die gebundene Funktion als zweites Argument empfangen. Wenn Sie den Teilanwendungsartikel noch nicht gelesen haben, tun Sie es, es sollte die Dinge klarer machen. –

Verwandte Themen