Zuvor haben wir das Funktionsprinzip von JavaScript anhand des Analysemechanismus der JavaScript-Engine untersucht. Jetzt verwenden wir ein anschaulicheres Beispiel, um die Ausführungsreihenfolge von JavaScript-Code auf der Seite zu veranschaulichen. Wenn der Arbeitsmechanismus der JavaScript-Engine relativ tiefgreifend ist, weil er zum zugrunde liegenden Verhalten gehört, ist die Ausführungsreihenfolge des JavaScript-Codes anschaulicher, da wir diese Ausführungsreihenfolge natürlich intuitiv spüren können ist relativ komplex, daher ist es auch notwendig, die JavaScript-Sprache zu profilieren, bevor man sich damit beschäftigt.
1.1 Führen Sie JavaScript-Code in der Reihenfolge des HTML-Dokumentflusses aus
Zunächst sollten Leser wissen, dass der Parsing-Prozess von HTML-Dokumenten im Browser wie folgt abläuft: Der Browser analysiert die Seitenstruktur und die Informationen schrittweise von oben nach unten entsprechend dem Dokumentfluss. JavaScript-Code als eingebettetes Skript sollte ebenfalls als Bestandteil des HTML-Dokuments gezählt werden, daher wird die Ausführungsreihenfolge des JavaScript-Codes beim Laden auch anhand der Reihenfolge bestimmt, in der das Skript-Tag <script> erscheint. Durchsuchen Sie beispielsweise die Dokumentationsseite unten und Sie werden sehen, dass der Code Schritt für Schritt von oben nach unten analysiert wird.
Kopieren Sie den Codecode wie folgt:
<Skript>
alarm("Top-Skript");
</script>
<html><head>
<Skript>
alarm("head script");
</script>
<title></title>
</head>
<Körper>
<Skript>
Alert("Seitenskript");
</script>
</body></html>
<Skript>
alarm("bottom script");
</script>
Wenn ein externes JavaScript-Dateiskript über das src-Attribut des Skript-Tags <script> importiert wird, wird es auch in der Reihenfolge ausgeführt, in der seine Anweisungen erscheinen, und der Ausführungsprozess ist Teil des Dokumentladens. Die Ausführung wird nicht verzögert, da es sich um eine externe JavaScript-Datei handelt. Verschieben Sie beispielsweise die Skripte im Kopf- und Textbereich des Dokuments oben in externe JavaScript-Dateien und importieren Sie sie dann über das src-Attribut. Wenn Sie die Vorschau des Seitendokuments fortsetzen, sehen Sie die gleiche Ausführungsreihenfolge.
Kopieren Sie den Codecode wie folgt:
<Skript>
alarm("Top-Skript");
</script>
<html>
<Kopf>
<script src="//www.VeVB.COm/head.js"></script>
<title></title>
</head>
<Körper>
<script src="//www.VeVB.COm/body.js"></script>
</body>
</html>
<Skript>
alarm("bottom script");
</script>
1.2 Die Beziehung zwischen Vorkompilierung und Ausführungsreihenfolge
In Javascript ist Funktion der erste Typ von Javascript. Wenn wir eine Funktion schreiben, erstellen wir eigentlich nur eine Entität vom Typ Funktion.
So wie wir es in dieser Form schreiben können:
Kopieren Sie den Codecode wie folgt:
functionHello()
{
alarm("Hallo");
}
Hallo();
varHello = function()
{
alarm("Hallo");
}
Hallo();
Tatsächlich sind sie alle gleich. Aber wenn wir die Funktionen ändern, werden wir auf sehr seltsame Probleme stoßen.
Kopieren Sie den Codecode wie folgt:
<scripttype="text/javascript">
functionHello() {
alarm("Hallo");
}
Hallo();
functionHello() {
alarm("Hallo Welt");
}
Hallo();
</script>
Das Ergebnis sehen wir so: Hello World wird zweimal hintereinander ausgegeben.
Anstelle der Hallo- und Hallo-Welt, die wir uns vorgestellt haben.
Dies liegt daran, dass Javascript nicht vollständig interpretiert und in der richtigen Reihenfolge ausgeführt wird. Während des Vorkompilierungsprozesses werden definierte Funktionen zuerst erstellt und der Standardwert ist undefiniert Effizienz der Programmausführung.
Mit anderen Worten, der obige Code wird tatsächlich von der JS-Engine in dieser Form vorkompiliert:
Kopieren Sie den Codecode wie folgt:
<scripttype="text/javascript">
varHello = function() {
alarm("Hallo");
}
Hallo = function() {
alarm("Hallo Welt");
}
Hallo();
Hallo();
</script>
Aus dem obigen Code können wir deutlich erkennen, dass Funktionen auch Daten und Variablen sind. Wir können „Funktionen“ auch Werte zuweisen (neu zuweisen).
Um diese Situation zu verhindern, können wir natürlich auch Folgendes tun:
Kopieren Sie den Codecode wie folgt:
<scripttype="text/javascript">
functionHello() {
alarm("Hallo");
}
Hallo();
</script>
<scripttype="text/javascript">
functionHello() {
alarm("Hallo Welt");
}
Hallo();
</script>
Auf diese Weise wird das Programm in zwei Abschnitte unterteilt, die von der JS-Engine nicht zusammengesetzt werden.
Wenn die JavaScript-Engine ein Skript analysiert, verarbeitet sie während der Vorkompilierung alle deklarierten Variablen und Funktionen.
Gehen Sie wie folgt vor:
1. Vor der Ausführung wird eine Operation ähnlich der „Vorkompilierung“ ausgeführt: Zunächst wird ein aktives Objekt in der aktuellen Ausführungsumgebung erstellt und die mit var deklarierten Variablen werden als Attribute des aktiven Objekts festgelegt, jedoch zu diesem Zeitpunkt , die Zuweisung dieser Variablen ist undefiniert, und die mit Funktion definierten Funktionen werden auch als Eigenschaften des aktiven Objekts hinzugefügt, und ihre Werte entsprechen genau der Definition der Funktion.
2. Wenn eine Variable während der Interpretations- und Ausführungsphase analysiert werden muss, wird sie zunächst im aktiven Objekt der aktuellen Ausführungsumgebung durchsucht. Wenn sie nicht gefunden wird und der Besitzer der Ausführungsumgebung über das Prototypattribut verfügt, wird sie verwendet Die Suche erfolgt in der Prototypenkette, andernfalls erfolgt die Suche anhand der Bereichskette. Wenn Sie auf eine Anweisung wie var a = ... stoßen, wird der entsprechenden Variablen ein Wert zugewiesen (Hinweis: Die Zuweisung der Variablen wird während der Interpretations- und Ausführungsphase abgeschlossen. Wenn die Variable zuvor verwendet wird, wird ihr Wert angezeigt undefiniert). Daher scheint es, dass kein Fehler gemeldet wird, wenn der JavaScript-Interpreter das folgende Skript ausführt:
Kopieren Sie den Codecode wie folgt:
Alert(a); // Rückgabewert undefiniert
var a =1;
alarm(a); // Rückgabewert 1
Da Variablendeklarationen zum Zeitpunkt der Vorkompilierung verarbeitet werden, sind sie während der Ausführung für den gesamten Code sichtbar. Sie werden jedoch auch feststellen, dass beim Ausführen des obigen Codes der angeforderte Wert undefiniert und nicht 1 ist. Dies liegt daran, dass der Variableninitialisierungsprozess während der Ausführung und nicht vor der Kompilierung erfolgt. Während der Ausführung analysiert der JavaScript-Interpreter den Code der Reihe nach. Wenn einer Variablen in der vorherigen Codezeile kein Wert zugewiesen wurde, verwendet der JavaScript-Interpreter den Standardwert undefiniert. Da der Variablen a in der zweiten Zeile ein Wert zugewiesen wird, wird die dritte Codezeile darauf hinweisen, dass der Wert der Variablen a 1 und nicht undefiniert ist.
Ebenso ist es im folgenden Beispiel zulässig, die Funktion aufzurufen, bevor die Funktion deklariert wird und korrekt analysiert werden kann, sodass der Rückgabewert 1 ist.
Kopieren Sie den Codecode wie folgt:
f(); // Funktion aufrufen, Rückgabewert 1
Funktion f(){
Warnung(1);
}
Wenn die Funktion jedoch wie folgt definiert ist, wird der JavaScript-Interpreter einen Syntaxfehler auslösen.
Kopieren Sie den Codecode wie folgt:
f(); // Funktion aufrufen und Syntaxfehler zurückgeben
var f = function(){
Warnung(1);
}
Dies liegt daran, dass die im obigen Beispiel definierte Funktion nur der Variablen f als Wert zugewiesen wird. Daher kann der JavaScript-Interpreter während der Vorkompilierungsphase nur die Deklaration der Variablen f und nur den Wert der Variablen f verarbeiten Wenn die Zuweisungen nacheinander ausgeführt werden, tritt natürlich ein Syntaxfehler auf, der dazu führt, dass das Objekt f nicht gefunden werden kann.
Tschüss, einige Beispiele:
Kopieren Sie den Codecode wie folgt:
<script type="text/javascript">
/*Während des Vorkompilierungsprozesses ist func ein Attribut im aktiven Objekt in der Fensterumgebung und der Wert ist eine Funktion, die den undefinierten Wert abdeckt*/
alarm(func); //function func(){alert("hello!")}
var func = „das ist eine Variable“
Funktion func(){
alarm("Hallo!")
}
/*Während der Ausführung wurde var gefunden und „Dies ist eine Variable“ neu zugewiesen*/
alarm(func); //das ist eine Variable
</script>
Kopieren Sie den Codecode wie folgt:
<script type="text/javascript">
var name = "feng" function func();
{
/*Zuerst den Namen undefiniert in der Funkumgebung zuweisen und dann während der Ausführung nach dem Namensattribut des aktiven Objekts in der Funkumgebung suchen. Zu diesem Zeitpunkt wurde der Wert auf undefiniert vorkompiliert, sodass die Ausgabe undefiniert ist feng */
alarm(name); //undefiniert var name = "JSF";
alarm(name); //JSF
}
func();
Warnung(Name);
//feng
</script>
Obwohl Variablen- und Funktionsdeklarationen an beliebiger Stelle im Dokument stehen können, empfiehlt es sich, globale Variablen und Funktionen vor dem gesamten JavaScript-Code zu deklarieren und Variablen zu initialisieren und zuzuweisen. Innerhalb einer Funktion werden Variablen zuerst deklariert und dann referenziert.
1.3 Führen Sie JavaScript-Code in Blöcken aus
Die sogenannten Codeblöcke sind durch <script>-Tags getrennte Codesegmente. Die beiden <script>-Tags unten stellen beispielsweise zwei JavaScript-Codeblöcke dar.
Kopieren Sie den Codecode wie folgt:
<Skript>
// JavaScript-Codeblock 1
var a =1;
</script>
<Skript>
// JavaScript-Codeblock 2
Funktion f(){
Warnung(1);
}
</script>
Wenn der JavaScript-Interpreter ein Skript ausführt, führt er es in Blöcken aus. Laienhaft ausgedrückt: Wenn der Browser beim Parsen des HTML-Dokumentstroms auf ein <script>-Tag stößt, wartet der JavaScript-Interpreter, bis der Codeblock geladen ist, kompiliert den Codeblock zunächst vor und führt ihn dann aus. Nach der Ausführung analysiert der Browser den folgenden HTML-Dokumentstrom weiter und der JavaScript-Interpreter ist bereit, den nächsten Codeblock zu verarbeiten.
Da JavaScript in Blöcken ausgeführt wird, wird beim Aufrufen einer Variablen oder Funktion, die in einem nachfolgenden Block in einem JavaScript-Block deklariert wird, ein Syntaxfehler angezeigt. Wenn der JavaScript-Interpreter beispielsweise den folgenden Code ausführt, wird ein Syntaxfehler angezeigt, der anzeigt, dass die Variable a undefiniert ist und das Objekt f nicht gefunden werden kann.
Kopieren Sie den Codecode wie folgt:
<Skript>
// JavaScript-Codeblock 1
Warnung(a);
F();
</script>
<Skript>
// JavaScript-Codeblock 2
var a =1;
Funktion f(){
Warnung(1);
}
</script>
Obwohl JavaScript in Blöcken ausgeführt wird, gehören verschiedene Blöcke zum gleichen globalen Bereich, was bedeutet, dass Variablen und Funktionen zwischen Blöcken gemeinsam genutzt werden können.
1.4 Verwenden Sie den Ereignismechanismus, um die Reihenfolge der JavaScript-Ausführung zu ändern
Da JavaScript Code in Blöcken verarbeitet und der Analysereihenfolge des HTML-Dokumentflusses folgt, werden Sie im obigen Beispiel solche Syntaxfehler sehen. Wenn der Dokumentenstrom jedoch geladen ist, tritt ein solcher Fehler nicht auf, wenn erneut darauf zugegriffen wird. Wenn beispielsweise der Code, der auf die Variablen und Funktionen im zweiten Codeblock zugreift, in der Ereignisfunktion zur Seiteninitialisierung platziert wird, treten keine Syntaxfehler auf.
Kopieren Sie den Codecode wie folgt:
<Skript>
// JavaScript-Codeblock 1
window.onload = function(){ // Funktion zur Behandlung von Seiteninitialisierungsereignissen
Warnung(a);
F();
}
</script>
<Skript>
// JavaScript-Codeblock 2
var a =1;
Funktion f(){
Warnung(1);
}
</script>
Aus Sicherheitsgründen erlauben wir die Ausführung von JavaScript-Code im Allgemeinen erst nach der Initialisierung der Seite. Dadurch können die Auswirkungen der Netzwerkgeschwindigkeit auf die JavaScript-Ausführung und auch die durch den HTML-Dokumentfluss verursachten Einschränkungen bei der JavaScript-Ausführung vermieden werden.
Beachten
Wenn auf einer Seite mehrere Windows.onload-Ereignishandler vorhanden sind, ist nur der letzte gültig. Um dieses Problem zu lösen, können Sie alle Skripte oder aufrufenden Funktionen in denselben Onload-Ereignishandler einfügen, zum Beispiel:
Kopieren Sie den Codecode wie folgt:
window.onload = function(){
f1();
f2();
f3();
}
Und auf diese Weise kann die Ausführungsreihenfolge von Funktionen geändert werden, indem einfach die Reihenfolge der Aufruffunktionen im Onload-Event-Handler angepasst wird.
Zusätzlich zu Seiteninitialisierungsereignissen können wir die Ausführungsreihenfolge von JavaScript-Code auch durch verschiedene interaktive Ereignisse wie Mausereignisse, Tastaturereignisse, Uhrauslöser usw. ändern. Eine ausführliche Erläuterung finden Sie in Kapitel 14.
1.5 Ausführungsreihenfolge von JavaScript-Ausgabeskripten
In der JavaScript-Entwicklung wird häufig die write()-Methode des Dokumentobjekts zur Ausgabe von JavaScript-Skripten verwendet. Wie werden diese dynamischen Ausgabeskripte ausgeführt? Zum Beispiel:
Kopieren Sie den Codecode wie folgt:
document.write('<script type="text/javascript">');
document.write('f();');
document.write('function f(){');
document.write('alert(1);');
document.write('}');
document.write('</script>');
Wenn wir den obigen Code ausführen, werden wir Folgendes feststellen: Die Methode document.write() schreibt zuerst die Ausgabeskriptzeichenfolge an den Speicherort des Dokuments, an dem sich das Skript befindet. Nach dem Parsen des Inhalts des Dokuments, an dem sich document.write() befindet Der Browser analysiert weiterhin den Ausgabeinhalt von document.write () und analysiert dann die nachfolgenden HTML-Dokumente der Reihe nach. Mit anderen Worten: Die vom JavaScript-Skript ausgegebene Codezeichenfolge wird unmittelbar nach der Ausgabe ausgeführt.
Bitte beachten Sie, dass die mit der Methode document.write() ausgegebene JavaScript-Skriptzeichenfolge im gleichzeitig ausgegebenen <script>-Tag platziert werden muss. Andernfalls kann der JavaScript-Interpreter diese zulässigen JavaScript-Codes nicht erkennen als gewöhnliche Zeichenfolge im Seitendokument angezeigt werden. Der folgende Code zeigt beispielsweise den JavaScript-Code an, anstatt ihn auszuführen.
Kopieren Sie den Codecode wie folgt:
document.write('f();');
document.write('function f(){');
document.write('alert(1);');
document.write(');');
Allerdings birgt die Ausgabe und Ausführung von Skripten über die Methode document.write() gewisse Risiken, da verschiedene JavaScript-Engines sie in unterschiedlicher Reihenfolge ausführen und beim Parsen in verschiedenen Browsern Fehler auftreten können.
Ø Problem 1: Die in der externen JavaScript-Datei deklarierten Variablen oder Funktionen, die über die Methode document.write() importiert wurden, können nicht gefunden werden. Schauen Sie sich zum Beispiel den folgenden Beispielcode an.
Kopieren Sie den Codecode wie folgt:
document.write('<script type="text/javascript" src="//www.VeVB.COm/test.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(n);'); // IE meldet, dass die Variable n nicht gefunden werden kann
document.write('</script>');
Alert(n+1); // Alle Browser melden, dass die Variable n nicht gefunden werden kann
Der Code der externen JavaScript-Datei (test.js) lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
var n = 1;
Beim Testen in verschiedenen Browsern werden Sie einen Syntaxfehler feststellen und die Variable n kann nicht gefunden werden. Mit anderen Worten: Wenn Sie in einem JavaScript-Codeblock auf die Variablen zugreifen, die in der externen JavaScript-Datei enthalten sind, die in die Skriptausgabe durch die Methode document.write() in diesem Codeblock importiert wurde, wird ein Syntaxfehler angezeigt. Wenn im IE-Browser nicht nur das Skript, sondern auch das Ausgabeskript angezeigt wird, wird gleichzeitig angezeigt, dass die in die externe JavaScript-Datei importierte Ausgabevariable nicht gefunden werden kann (der Ausdruck ist etwas lang und kompliziert). Leser, die es nicht verstehen, können versuchen, den obigen Code auszuführen (kann verstanden werden).
Ø Frage 2: Verschiedene JavaScript-Engines haben leicht unterschiedliche Ausführungsreihenfolgen für die Ausgabe externer Importskripte. Schauen Sie sich zum Beispiel den folgenden Beispielcode an.
Kopieren Sie den Codecode wie folgt:
<script type="text/javascript">
document.write('<script type="text/javascript" src="http://shaozhuqing.com/test1.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(2);')
document.write('alert(n+2);');
document.write('</script>');
</script>
<script type="text/javascript">
alarm(n+3);
</script>
Der Code für die externe JavaScript-Datei (test1.js) wird unten angezeigt.
Kopieren Sie den Codecode wie folgt:
var n = 1;
alarm(n);
Die Ausführungssequenz im IE-Browser ist in Abbildung 1-6 dargestellt.
Abbildung 1-6 Die vom IE 7-Browser ausgelöste Ausführungssequenz und Syntaxfehler
Die Ausführungsreihenfolge in Browsern, die den DOM-Standards entsprechen, unterscheidet sich von der in IE-Browsern, und es gibt keine Syntaxfehler. Abbildung 1-7 zeigt die Ausführungsreihenfolge im Firefox 3.0-Browser.
Abbildung 1-7 Ausführungssequenz und Syntaxfehler des Firefox 3-Browsers werden angezeigt
Beheben Sie die unterschiedlichen Ausführungsreihenfolgen verschiedener Browser und mögliche Fehler. Wir können alle mit dem Ausgabeskript importierten externen Dateien in unabhängige Codeblöcke einfügen, sodass dieses Problem entsprechend der Ausführungsreihenfolge der oben eingeführten JavaScript-Codeblöcke vermieden werden kann. Für das obige Beispiel können Sie es beispielsweise so gestalten:
Kopieren Sie den Codecode wie folgt:
<script type="text/javascript">
document.write('<script type="text/javascript" src="//www.VeVB.COm/test1.js"></script>');
</script>
<script type="text/javascript">
document.write('<script type="text/javascript">');
document.write('alert(2);') ; // Tipp 2
document.write('alert(n+2);' // Tipp 3
document.write('</script>');
alarm(n+3); // Tipp 4
</script>
<script type="text/javascript">
alarm(n+4); // Tipp 5
</script>
Auf diese Weise kann der obige Code der Reihe nach in verschiedenen Browsern ausgeführt werden und die Ausgabereihenfolge ist 1, 2, 3, 4 und 5. Der Grund für das Problem ist: ein Widerspruch zwischen dem ausgegebenen importierten Skript und dem aktuellen JavaScript-Codeblock. Bei separater Ausgabe entsteht kein Konflikt.