Heim > Artikel > Web-Frontend > Besprechen Sie den Ausführungsprozess von JavaScript-Anweisungen_Javascript-Fähigkeiten
Kommen wir ohne weitere Umschweife direkt zur Sache. Das Funktionsprinzip von Javascript lässt sich wie folgt zusammenfassen:
1. Führen Sie Javascript-Code in der Reihenfolge des HTML-Dokumentflusses aus
Der Browser analysiert die Seitenstruktur und die Informationen schrittweise von oben nach unten entsprechend dem Dokumentfluss. Der Javascript-Code ist ein eingebettetes Skript und eine Komponente des HTML-Dokuments, daher basiert auch die Ausführungsreihenfolge des Javascript-Codes beim Laden auf dem Skript-Tag 3f1c4e4b6b16bbbd69b2ee476dc4f83a wird durch die Reihenfolge bestimmt, in der sie erscheinen.
Wenn eine externe .js-Datei über das src-Attribut des Skript-Tags 3f1c4e4b6b16bbbd69b2ee476dc4f83a eingeführt wird, wird sie auch in der Reihenfolge ausgeführt, in der ihre Anweisungen erscheinen, und der Ausführungsprozess ist Teil des Dokumentladens. Die Ausführung wird nicht verzögert, da es sich um eine externe JS-Datei handelt.
2. Die Beziehung zwischen Vorkompilierung und Ausführungsreihenfolge
Schauen Sie sich zunächst den folgenden Code an:
<script type="text/javascript"> function hello() { alert("hello"); } hello(); function hello() { alert("hello world"); } hello(); </script>
Das Ausgabeergebnis des obigen js-Codes ist „Hallo Welt, hallo Welt“, anstatt zuerst „Hallo“ und dann „Hallo Welt“ auszugeben. Dies liegt daran, dass JavaScript nicht vollständig der Reihe nach interpretiert und ausgeführt wird, sondern dass JavaScript vor der Interpretation vorkompiliert wird. Während des Vorkompilierungsprozesses werden definierte Funktionen zuerst ausgeführt und alle Variablenvariablen werden standardmäßig erstellt um die Effizienz der Programmausführung zu verbessern. Mit anderen Worten, der obige Code wird tatsächlich von der JS-Engine wie folgt vorkompiliert:
<script type="text/javascript"> var hello = function() { alert("hello"); }; hello = function() { alert("hello world"); }; hello(); hello(); </script>
Aus dem obigen Code können Sie deutlich erkennen, dass Funktionen tatsächlich Variablen sind und Funktionen Werte zugewiesen werden können. Um das Auftreten der vorherigen Situation zu verhindern, kann es wie folgt in zwei js-Dateien definiert werden:
<script type="text/javascript"> hello(); function hello() { alert("hello"); } // hello(); </script> <script type="text/javascript"> function hello() { alert("hello world"); } hello(); </script>
In der ersten Datei oben habe ich hello() vor die Funktion gesetzt, und das korrekte Ergebnis kann ausgegeben werden.
<script type="text/javascript"> hello(); var hello = function() { alert("hello"); }; // hello(); </script>
Wenn Sie die obige Methode zum Definieren der Funktionsfunktion verwenden, wird ein Fehler gemeldet. Die Fehlermeldung ist wie in Abbildung 1 unten dargestellt:
Der Fehler „Hallo ist keine Funktion“ wird hier gemeldet. Dies liegt daran, dass während der Vorkompilierung die mit var deklarierten Variablen zuerst verarbeitet werden, der Variablenwert jedoch undefiniert ist. Wenn Sie dann hello () ausführen, ist hello hier keine Funktion, da das vorherige hello undefiniert ist und der Typ nicht bestimmt ist. Obwohl diese Funktion im Programm definiert ist, wird der Speicherort der Definition nach dem Aufruf platziert. Wenn also der Aufruf erfolgt, wird das Programm hier nicht ausgeführt und ist daher nutzlos.
Sehen Sie sich den folgenden Code an:
<script type="text/javascript"> hello(); function hello() { alert("hello"); } // hello(); </script>
Obwohl der obige Code vor der Funktionsdefinition aufgerufen wird, wird er mit dem Funktionsschlüsselwort definiert. Wenn die Funktion definiert ist, ist der Wert der Funktion bereits festgelegt Vergangenheit, sodass es hier ausgeführt werden kann.
Zusammenfassung:
Wenn die JavaScript-Engine das Skript analysiert, verarbeitet sie alle deklarierten Variablen und Funktionen während der Vorkompilierung. Die Verarbeitung ist wie folgt:
(1) Eine ähnliche „Vorkompilierungs“-Operation wird vor der Ausführung durchgeführt: Zuerst wird ein aktives Objekt in der aktuellen Ausführungsumgebung erstellt und die mit var deklarierten Variablen werden als Attribute des aktiven Objekts festgelegt. Aber zu diesem Zeitpunkt sind diese Variablenzuweisungen alle 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 Eigentümer der Ausführungsumgebung über die Variable verfügt Prototypattribut, es wird in der Prototypenkette gesucht, andernfalls wird es anhand der Bereichskette durchsucht. Wenn eine Anweisung wie var a = ... angetroffen wird, 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 zugewiesen undefiniert sein).
(3) Zusammenfassend lautet die Zusammenfassung in einem Satz: Die Deklaration von Variablen erfolgt in der Zeit vor der Kompilierung und die Initialisierung von Variablen erfolgt in der Laufzeit.
<script type="text/javascript"> alert(a); // 在预编译期间a变量已经加载,但是用var定义,所以赋值为undefined先,故这里输出undefined。 var a = 1; // 这里给前面的没有赋值的a进行赋值为1 alert(a); // 这里输出的a已经是前面赋值过的,所以输出1。 </script>
Für den obigen Code lautet das Ausgabeergebnis: Zuerst wird undefiniert und dann 1 ausgegeben. Zur Analyse siehe die Codebemerkungen.
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.
3. Javascript-Code in Blöcken ausführen
Der sogenannte Codeblock ist ein durch 3f1c4e4b6b16bbbd69b2ee476dc4f83a getrenntes Codesegment. 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 3f1c4e4b6b16bbbd69b2ee476dc4f83a-Tag stößt, wartet der JavaScript-Interpreter, bis der Codeblock geladen ist, kompiliert den Codeblock 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.
<script> alert(a); </script> <script> var a = 1; </script>
上面的这段代码,由于是两个代码块,先执行完第一个代码块,再执行第二个代码块。执行第一个代码块的时候,变量a没有声明,所以报错,报错信息是:a is not defined。
<script> var a = 1; </script> <script> alert(a); </script>
虽然说,JavaScript是按块执行的,但是不同块都属于同一个全局作用域,也就是说,块之间的变量和函数是可以共享的。所以,上面的这两个代码块运行的时候,虽然是两个代码块,但是第一段运行以后,a变量就存在了全局作用域中,此时运行到第二个代码块,输出的a变量就可以调用全局作用域中的a,所以没有问题。
4、借助事件机制改变javascript执行顺序
由于JavaScript是按块处理代码,同时又遵循HTML文档流的解析顺序,所以在上面示例中会看到这样的语法错误。但是当文档流加载完毕,如果再次访问就不会出现这样的错误。为了安全起见,我们一般在页面初始化完毕之后才允许JavaScript代码执行,这样可以避免网速对JavaScript执行的影响,同时也避开了HTML文档流对于JavaScript执行的限制。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>javascript</title> <script> window.onload = function() { alert(a); }; </script> <script> var a = 1; alert("bb"); </script> </head> <body> </body> <script> alert("cc"); </script> </html>
windows.onload = function()表示先在触发事件上加一个函数,并不立即执行,而是在整个页面都加载完成以后再开始执行该事件,及function。所以,在windows.onload执行之前,就已经把一些变量加载到了全局区中,所以没有问题。上面的输出结果是:先输出bb,再输出cc,最后输出a。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>javascript</title> <script> window.onload = function() { alert(a); }; // 上面的onload不会执行,只会执行下面的onload window.onload = function() { alert("onload2"); }; </script> <script> var a = 1; alert("bb"); </script> </head> <body> </body> <script> alert("cc"); </script> </html>
如果在一个页面中存在多个windows.onload事件处理函数,则只有最后一个才是有效的(如上面的代码所示),为了解决这个问题,可以把所有脚本或调用函数都放在同一个onload事件处理函数中,如下面的代码所示:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>javascript</title> <script> window.onload = function() { // 放到一起 alert(a); alert("onload2"); }; </script> <script> var a = 1; alert("bb"); </script> </head> <body> </body> <script> alert("cc"); </script> </html>
5、javascript输出脚本的执行顺序
在JavaScript开发中,经常会使用document对象的write()方法输出JavaScript脚本。document.write()方法先把输出的脚本字符串写入到脚本所在的文档位置,浏览器在解析完document.write()所在文档内容后,继续解析document.write()输出的内容,然后才按顺序解析后面的HTML文档。也就是说,JavaScript脚本输出的代码字符串会在输出后马上被执行。请注意,使用document.write()方法输出的JavaScript脚本字符串必须放在同时被输出的3f1c4e4b6b16bbbd69b2ee476dc4f83a标签中,否则JavaScript解释器因为不能够识别这些合法的JavaScript代码,而作为普通的字符串显示在页面文档中。但是,通过document.write()方法输出脚本并执行也存在一定的风险,因为不同JavaScript引擎对其执行顺序不同,同时不同浏览器在解析时也会出现Bug。
以上所述是小编给大家介绍的JavaScript语句的执行过程,希望对大家有所帮助。