Funktionsaufrufe
Funktionen sind nur eine Art Objekt.
Alle Funktionsobjekte verfügen über Methoden zum Aufrufen und Anwenden , mit denen das aufgerufene Funktionsobjekt ausgeführt wird.
Beim Aufruf gibt das erste Argument für diese Methoden das Objekt an, auf das das thisSchlüsselwort während der Ausführung der Funktion verweist - wenn es nulloder undefineddas globale Objekt windowfür verwendet wird this.
Aufrufen einer Funktion ...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
... mit Klammern - foo()- entspricht foo.call(undefined)oder foo.apply(undefined), was praktisch dasselbe ist wie foo.call(window)oder foo.apply(window).
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
Zusätzliche Argumente, calldie als Argumente an den Funktionsaufruf übergeben werden sollen, während ein einzelnes zusätzliches Argument applydie Argumente für den Funktionsaufruf als Array-ähnliches Objekt angeben kann.
Somit foo(1, 2, 3)ist äquivalent zu foo.call(null, 1, 2, 3)oder foo.apply(null, [1, 2, 3]).
>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"
Wenn eine Funktion eine Eigenschaft eines Objekts ist ...
var obj =
{
whereAmI: "obj",
foo: foo
};
... der Zugriff auf einen Verweis auf die Funktion über das Objekt und der Aufruf mit Klammern - obj.foo()- entspricht foo.call(obj)oder foo.apply(obj).
Funktionen, die als Eigenschaften von Objekten gehalten werden, sind jedoch nicht an diese Objekte "gebunden". Wie Sie in der objobigen Definition sehen können , können Funktionen, da sie nur eine Art von Objekt sind, referenziert werden (und somit als Referenz auf einen Funktionsaufruf übergeben oder als Referenz von einem Funktionsaufruf zurückgegeben werden). Wenn ein Verweis auf eine Funktion übergeben wird, werden keine zusätzlichen Informationen darüber mitgeführt, woher er übergeben wurde. Aus diesem Grund geschieht Folgendes:
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
Der Aufruf unserer Funktionsreferenz bazbietet keinen Kontext für den Aufruf, ist also praktisch derselbe wie baz.call(undefined), führt also zu thiseiner Referenzierung window. Wenn wir bazwissen wollen , dass es dazu gehört, objmüssen wir diese Informationen irgendwie bereitstellen, wenn sie bazaufgerufen werden. Hier kommt das erste Argument für calloder applyund Schließungen ins Spiel.
Zielfernrohrketten
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
Wenn eine Funktion ausgeführt wird, erstellt sie einen neuen Bereich und verweist auf einen beliebigen umschließenden Bereich. Wenn die anonyme Funktion im obigen Beispiel erstellt wird, verweist sie auf den Bereich, in dem sie erstellt wurde. Dies ist bindder Bereich. Dies ist als "Verschluss" bekannt.
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
Wenn Sie versuchen, auf eine Variable zuzugreifen, wird diese "Bereichskette" durchlaufen, um eine Variable mit dem angegebenen Namen zu finden. Wenn der aktuelle Bereich die Variable nicht enthält, sehen Sie sich den nächsten Bereich in der Kette an und so weiter, bis Sie ihn erreichen der globale Umfang. Wenn die anonyme Funktion zurückgegeben wird und die bindAusführung abgeschlossen ist, hat die anonyme Funktion immer noch einen Verweis auf bindden Gültigkeitsbereich, sodass bindder Gültigkeitsbereich nicht "verschwindet".
Angesichts all der oben genannten Punkte sollten Sie nun in der Lage sein zu verstehen, wie der Gültigkeitsbereich im folgenden Beispiel funktioniert und warum die Technik zum Übergeben einer Funktion um "vorgebunden" mit einem bestimmten Wert thisfunktioniert, wenn sie aufgerufen wird:
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"
var signup = { onLoadHandler:function(){ console.log(this); return Type.createDelegate(this,this._onLoad); }, _onLoad: function (s, a) { console.log("this",this); }};