Ich ging vorgestern zu einem Vorstellungsgespräch und ein gg fragte mich nach einigen JS-Kenntnissen. Es gab eine Frage zur Verwendung von „Call“ und „Apply“. Obwohl ich die Call-Methode vor 365 Tagen verwendet hatte, konnte ich sie immer noch nicht beantworten Damals werde ich es heute ausführlich zusammenfassen.
Beim Aufrufen und Anwenden besteht die Funktion darin, die Funktion zur Ausführung an ein anderes Objekt zu binden.
Die Format- und Parameterdefinitionen von beiden:
call( thisArg [, arg1, arg2, ... ] ); // Parameterliste, arg1, arg2, ...
apply(thisArg [, argArray]); // Parameterarray, argArray
Dem Zeiger this innerhalb der beiden oben genannten Funktionen wird thisArg zugewiesen, wodurch der Zweck der Ausführung der Funktion als Methode eines anderen Objekts realisiert werden kann.
1. Einfache Nutzung des Anrufs
Schauen wir uns zunächst ein einfaches Beispiel (Aufruf) an:
Kopieren Sie den Codecode wie folgt:
<!doctype html>
<html>
<Kopf>
<title> call-apply </title>
</head>
<Körper>
<input type="text" id="idTxt" value="input text">
<script type="text/javascript">
var value = "globale Variable";
Funktion mFunc()
{
this.value = "member var";
}
Funktion gFunc()
{
alarm(this.value);
}
window.gFunc();// gFunc anzeigen, globale Variable
gFunc.call(window);// gFunc anzeigen, globale Variable
gFunc.call(new mFunc());// show mFunc, member var
gFunc.call(document.getElementById('idTxt'));// Element anzeigen, Text eingeben
</script>
<script language="javascript">
var func = neue Funktion()
{
this.a = "func";
}
var func2 = Funktion(x)
{
var a = "func2";
alarm(this.a);
alarm(x);
}
func2.call(func, "func2");// func und func2 anzeigen
</script>
</body>
</html>
Dann sind die laufenden Ergebnisse wie folgt:
globale Varglobale Var
Mitgliedsvar
Eingabetext
Funktion
Funktion2
Testumgebung: Google Chrome10.0.648.45
Analysieren Sie abschließend die Ergebnisse
1. Das globale Objektfenster ruft die Funktion gFunc auf und diese zeigt auf das Fensterobjekt, sodass this.value eine globale Variable ist.
2. Die Funktion gFunc ruft die Aufrufmethode auf. Dies zeigt standardmäßig auf das erste Parameterfensterobjekt, daher ist this.value auch eine globale Variable.
3. Die Funktion gFunc ruft die Aufrufmethode auf. Dies ist standardmäßig der erste Parameter new mFunc(), der das Objekt von mFunc ist. Daher ist this.value die Mitgliedsvariable von mFunc.
4. Die Funktion gFunc ruft die Aufrufmethode auf, die auf das erste Parameter-Eingabetext-Steuerelement verweist, also auf das Steuerelement mit der ID='idTxt'. Daher ist this.value der Werteingabetext des Eingabesteuerelements.
5. Funktion func2 ruft die Aufrufmethode auf. Dies ist standardmäßig der erste Parameter des Funktionsobjekts func, also ist this.value this.a, also func.
6. Die Funktion func2 ruft die Aufrufmethode auf. Der zweite Parameter gehört zum Parameter des Funktionsobjekts func2, daher ist Alert(x) der zweite Parameter func2.
2. Rufen Sie die Nutzung und Verbesserung der Vererbung auf
js verwendet einen Aufruf, um die Vererbung zu simulieren
Testcode:
Kopieren Sie den Codecode wie folgt:
<!doctype html>
<html>
<Kopf>
<title> Aufruf - Erben beantragen </title>
</head>
<Körper>
<script type="text/javascript">
Funktion baseA()// Basisklasse A
{
this.member = "baseA-Mitglied";
this.showSelfA = function()
{
window.alert(this.member);
}
}
Funktion baseB()// Basisklasse B
{
this.member = "baseB-Mitglied";
this.showSelfB = function()
{
window.alert(this.member);
}
}
Funktion extensionAB()// Klasse von A und B erben
{
baseA.call(this);// Aufruf für A
baseB.call(this);// Aufruf für B
}
window.onload = function()
{
var extension = new extensionAB();
extend.showSelfA();// A anzeigen
extend.showSelfB();// B anzeigen
}
</script>
</body>
</html>
Die Laufergebnisse sind wie folgt:baseB-Mitglied
baseB-Mitglied
Testumgebung: Google Chrome10.0.648.45
Ergebnisanalyse:
Das erwartete Ergebnis sollte die Ausgabe von baseA-Mitglied und baseB-Mitglied sein, aber die tatsächliche Ausgabe ist baseB-Mitglied und baseB-Mitglied.
(Es wurde in IE9, 8, 6, Maxthon, Chrome, FF, Opera, Safari, 360 und anderen Browsern getestet und das Ergebnis ist das letztere: baseB-Mitglied)
Zu diesem Zeitpunkt liegt die Maschine nicht falsch, weshalb wir eine eingehende Analyse durchführen müssen
Wir können leicht denken, dass dies darauf zurückzuführen ist. Dies zeigt zweimal auf das BaseB-Objekt, aber ist das wirklich der Fall?
Um das Wesentliche zu untersuchen, haben wir das Debugging-Tool des Chrome-Browsers zum Festlegen von Haltepunkten und zum Debuggen verwendet und Folgendes festgestellt:
Wenn „extend.showSelfA();“ aufgerufen wird, zeigt dies auf „extendAB“ (nicht auf das „baseB“-Objekt, wie wir zweimal vermutet haben).
Der wahre Grund besteht darin, dass das Mitgliedsvariablenmitglied des ExtendAB-Objekts durch das Mitgliedsmitglied von BaseB überschrieben wird, wenn es von baseB.call(this) instanziiert wird. Das heißt, das Mitgliedsmitglied von ExtendAB wird vom BaseA-Mitglied dem zugewiesen baseB-Mitglied.
Natürlich können wir den obigen baseA-Code auch leicht ändern, um die Richtigkeit unserer Debugging-Analyse zu überprüfen:
Kopieren Sie den Codecode wie folgt:
Funktion baseA()// Basisklasse A
{
this.memberA = "baseA member"; // member wird in memberA geändert, um das Mitglied in baseB zu unterscheiden
this.showSelfA = function()
{
window.alert(this.memberA); // MemberA anzeigen
}
}
Führen Sie Browser wie Chrome erneut aus. Die Ergebnisse sind wie folgt:
baseA-Mitglied
baseB-Mitglied
Die Ergebnisse entsprechen unseren Erwartungen und die Chrome-Debugging-Informationen bestätigen auch unsere Richtigkeit:
Vererbungsverbesserungen (Prototyp)
Die oben simulierte Vererbungsmethode ist nach sorgfältiger Analyse nicht die beste.
Denn jedes Mal, wenn eine Mitgliedsmethode in einer Funktion (Klasse) definiert wird, wird eine Kopie der Instanz erstellt, sodass Sie den Prototyp-Prototyp verwenden können, um Verbesserungen vorzunehmen.
Beispiele für Verbesserungen sind:
Kopieren Sie den Codecode wie folgt:
<!doctype html>
<html>
<Kopf>
<title> Aufruf – Prototyp beantragen </title>
</head>
<Körper>
<script type="text/javascript">
varClass = {
create: function()// create Function
{
Rückgabefunktion()
{
this.initialize.apply(this, arguments);
}
}
};
var Person = Class.create();// Klassenperson erstellen
Person.prototype = {// Prototyp initialisieren
initialisieren: Funktion(obj1, obj2)
{
this.obj1 = obj1;
this.obj2 = obj2;
},
showSelf: function()
{
alarm("obj: " + this.obj1 + " and " + this.obj2);
}
}
// Instanzklasse
var person = new Person("man", "women");// two params
person.showSelf();// Person anzeigen
</script>
</body>
</html>
Die Laufergebnisse sind wie folgt:
Objekt: Männer und Frauen