Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung des JavaScript-Funktionsmechanismus und konzeptionelle Analyse

Detaillierte Erläuterung des JavaScript-Funktionsmechanismus und konzeptionelle Analyse

零到壹度
零到壹度Original
2018-04-09 14:53:312001Durchsuche

Ich habe einen sehr vagen Eindruck von JavaScript. Es ist Single-Threaded und asynchron. In diesem Artikel geht es hauptsächlich um die Funktionsweise von JavaScript. Aber vorher wollen wir zunächst diese Konzepte verstehen (jetzt lernen und jetzt verkaufen) .

Grundlegende Konzepte

Threads und Prozesse

Prozess ist die Einheit der Systemressourcenzuweisung und -planung. Ein laufendes Programm entspricht einem Prozess. Ein Prozess umfasst laufende Programme sowie die von den Programmen verwendeten Speicher- und Systemressourcen. Wenn es sich um eine Single-Core-CPU handelt, läuft gleichzeitig nur ein Prozess. Eine Single-Core-CPU kann jedoch auch mehrere Aufgaben gleichzeitig ausführen. Sie können beispielsweise die täglich empfohlenen Songs von NetEase Cloud Music anhören, während Sie einen Blog-Beitrag auf NetEase Youdao Cloud Notes schreiben. Dies zählt als zwei Prozesse (Multiprozess). Der laufende Mechanismus besteht darin, eine Zeit lang Lieder abzuspielen und eine Zeit lang auf Ihre Eingabe zu reagieren. Da die CPU-Umschaltgeschwindigkeit jedoch sehr hoch ist, ist dies überhaupt nicht zu spüren. sodass Sie denken, dass diese beiden Prozesse gleichzeitig laufen. Ressourcen werden zwischen Prozessen isoliert.

Was ist ein Thread? Ein Thread ist der Executor unter einem Prozess. Ein Prozess startet mindestens einen Thread (den Hauptthread) und kann auch mehrere Threads starten. NetEase Cloud Music spielt beispielsweise Audio ab und zeigt gleichzeitig Liedtexte an. Der Multiprozessvorgang wird tatsächlich über Threads im Prozess ausgeführt. Threads unter einem Prozess teilen sich Ressourcen. Wenn mehrere Threads gleichzeitig dieselbe Ressource betreiben, kommt es zu Ressourcenkonflikten. Das ist eine andere Frage.

Parallelität und Parallelität

Parallelität bezieht sich auf den laufenden Status eines Programms, bei dem mehrere Dinge gleichzeitig parallel verarbeitet werden. Da ein Thread nur eine Sache gleichzeitig verarbeiten kann, erfordert die Parallelität, dass mehrere Threads mehrere Dinge gleichzeitig ausführen.

Parallelität bezieht sich auf die Designstruktur eines Programms, sodass mehrere Dinge abwechselnd gleichzeitig verarbeitet werden können. Der Punkt ist, dass jeweils nur eine Sache ausgeführt wird. Beispielsweise kann eine Single-Core-CPU den Prozess der gleichzeitigen Ausführung mehrerer Aufgaben realisieren.

Synchronisation und Asynchron

Synchronisation und Asynchronität beziehen sich auf das Verhalten des Programms. Synchron (synchron) bedeutet, dass das Programm bei einem Aufruf wartet, bis das Ergebnis zurückgegeben wird. Es wird erst dann zurückgegeben, wenn kein Ergebnis vorliegt. Mit anderen Worten liegt eine Synchronisierung vor, wenn der Anrufer aktiv auf den anrufenden Prozess wartet.

Asynchron bedeutet, unmittelbar nach dem Ausgeben eines Aufrufs zurückzukehren, das Ergebnis wird jedoch nicht sofort zurückgegeben. Der Anrufer muss nicht aktiv warten, wenn der Angerufene das Ergebnis erhält, wird er aktiv benachrichtigt.

Gehen Sie zum Beispiel in einen Milchteeladen, um Getränke zu kaufen. Synchronisierung bedeutet, dass ein Kunde einen Bedarf (Anfrage) angibt und dann darauf wartet, dass der Kellner das Getränk zubereitet. Der Kunde geht, nachdem er das bestellte Getränk erhalten hat, und der nächste Kunde wiederholt den oben genannten Vorgang. Asynchron bedeutet, dass sich die Kunden zuerst anstellen, um zu bestellen, und nach der Bestellung die Bestellung beiseite legen. Der Kellner ruft ihre Nummer an, wenn sie Sie anrufen, und Sie holen sie einfach ab.

Threads stehen also nicht in direktem Zusammenhang mit Synchronisation und Asynchronität, und ein einzelner Thread kann auch eine asynchrone Implementierung erreichen. Die Implementierungsmethode wird im Folgenden ausführlich erläutert.

Blockieren und Nicht-Blockieren

Blockieren und Nicht-Blockieren beziehen sich auf den Wartezustand. Blockieren bedeutet, dass der Thread „angehalten“ wird, während der Aufruf wartet (CPU-Ressourcen werden an anderer Stelle zugewiesen).

Nicht blockierend (Nicht blockierend) bedeutet, dass sich die CPU-Ressourcen des Warteprozesses noch im Thread befinden und der Thread auch andere Dinge tun kann.

Nehmen Sie das Beispiel des Anstehens, um gerade Getränke zu kaufen. Blockieren bedeutet, dass Sie während des Wartens nichts tun können.

Die Synchronisierung kann also blockierend oder nicht blockierend sein, und die asynchrone Synchronisierung kann blockierend oder nicht blockierend sein.

Single-Threaded JS

Nachdem Sie die oben genannten Konzepte grob verstanden haben, werden Sie wissen, dass es keinen Widerspruch zwischen Single-Threading und Asynchronität gibt. Wie wird JS ausgeführt? JS ist eigentlich eine Sprache. Ob es sich um eine Single-Thread- oder Multi-Thread-Sprache handelt, hängt von der jeweiligen Betriebsumgebung ab. JS wird normalerweise im Browser ausgeführt und von der JS-Engine analysiert und ausgeführt. Schauen wir uns den Browser genauer an.

Browser

Die derzeit beliebtesten Browser sind: Chrome, IE, Safari, Firefox, Opera. Der Kern des Browsers ist Multi-Threaded. Ein Browser besteht normalerweise aus den folgenden residenten Threads:

  • Rendering-Engine-Thread: Wie der Name schon sagt, ist dieser Thread für das Rendern der Seite verantwortlich

  • JS Engine-Thread: Verantwortlich für das Parsen und Ausführen von JS

  • Timing-Trigger-Thread: Verarbeitung von Timing-Ereignissen wie setTimeout, setInterval

  • Ereignisauslöser-Thread: Verarbeitung von DOM-Ereignissen

  • Asynchroner HTTP-Anforderungsthread: Verarbeitung von HTTP-Anforderungen

Es ist zu beachten, dass der Rendering-Thread und der JS Engine-Thread kann nicht gleichzeitig verarbeitet werden. Wenn der Rendering-Thread Aufgaben ausführt, wird der JS-Engine-Thread angehalten. Da JS das DOM manipulieren kann, ist der Browser möglicherweise ratlos, wenn JS das DOM während des Renderns verarbeitet.

JS-Engine

Wenn wir über Browser sprechen, sprechen wir normalerweise von zwei Engines: der Rendering-Engine und der JS-Engine. Die Rendering-Engine dient zum Rendern der Seite. Chrome/Safari/Opera verwenden die Webkit-Engine, IE verwendet die Trident-Engine und FireFox verwendet die Gecko-Engine. Verschiedene Engines implementieren denselben Stil inkonsistent, was zu dem oft kritisierten Problem der Browser-Stilkompatibilität führt. Wir werden hier nicht im Detail darauf eingehen.

Die JS-Engine kann als virtuelle JS-Maschine bezeichnet werden, die für das Parsen und Ausführen von JS-Code verantwortlich ist. Es umfasst normalerweise die folgenden Schritte:

  • Lexikalische Analyse: Zerlegen Sie den Quellcode in sinnvolle Wortsegmente

  • Syntaxanalyse: Verwenden Sie einen Syntaxanalysator. Parse die Wortsegmentierung in einen Syntaxbaum

  • Codegenerierung: Generieren Sie Code, den die Maschine ausführen kann

  • Codeausführung

Die JS-Engines verschiedener Browser sind ebenfalls unterschiedlich. Chrome verwendet V8, FireFox verwendet SpiderMonkey, Safari verwendet JavaScriptCore und IE verwendet Chakra.

Um auf die Aussage zurückzukommen, dass JS Single-Threaded ist: Im Wesentlichen öffnet der Browser nur einen JS-Engine-Thread, um JS zur Laufzeit zu analysieren und auszuführen. Warum also nur ein Motor? Wenn zwei Threads gleichzeitig das DOM betreiben, ist der Browser dann wieder ratlos? !

JS-Laufmechanismus

Nachdem wir so viel geredet haben, wollen wir endlich über den gesamten Laufprozess von JS sprechen.

Synchronisierte Ausführung

Schauen wir uns zunächst an, wie der JS-synchrone Ausführungsprozess erreicht wird. Dies beinhaltet ein sehr wichtiges Konzept – den Ausführungskontext. Eine meiner Übersetzungen, Deep Learning JavaScript Closures, erklärt dieses Konzept ausführlich.

Der Ausführungskontext zeichnet die Umgebung auf, in der der Code ausgeführt wird. Im aktuellen Ausführungsstatus ist ein Ausführungskontext wirksam. Was genau wird also im Ausführungskontext erfasst? Es gibt wahrscheinlich eine lexikalische Umgebung, eine variable Umgebung usw. Um ein einfaches Beispiel zu geben:

var x = 10;

function foo(){
    var y=20;
    function bar(){
        var z=15; 
    }
    bar();
}

foo();

Wenn der Code ausgeführt wird, tritt er zunächst in den globalen Kontext ein. Wenn dann foo() ausgeführt wird, wird der foo-Kontext eingegeben. Natürlich ist der globale Kontext zu diesem Zeitpunkt noch vorhanden. Wenn bar() ausgeführt wird, wird der Balkenkontext erneut eingegeben. Kehren Sie nach der Ausführung bar() zum Foo-Kontext zurück. Kehren Sie nach der Ausführung von foo() zum globalen Kontext zurück. Daher bildet der Ausführungskontext des Ausführungsprozesses einen Aufrufstapel (Aufrufstapel), zuerst rein, zuletzt raus.

// 进栈
                                                          3 bar Context
    =>                      =>   2 foo Context     =>     2 foo Context
        1 global Context         1 global Context         1 global Context

// 出栈
3 bar Context
2 foo Context     =>   2 foo Context     =>                        =>
1 global Context       1 global Context         1 global Context

Während der JS-Ausführung ist nur ein Ausführungskontext wirksam. Da JS Single-Threaded ist, kann es jeweils nur eine Aufgabe ausführen.

Die oben genannten Prozesse werden alle synchron ausgeführt.

Asynchrone Ausführung – Ereignisschleife

Sehen wir uns an, welche nativen asynchronen Ereignisse in JS vorkommen:

  • setTimeout

  • setInterval

  • Ereignis-Listener

  • Ajax-Anfrage

  • usw.

Der asynchrone Effekt von JS profitiert von der Ausführungsumgebung des Browsers. Tatsächlich öffnet der Browser einen weiteren Thread, um diese Stücklistenereignisse zu verarbeiten. Beispiel:

function foo(){
    console.log(1);
}

function bar(){
    console.log(2);
}

foo();

setTimeout(function cb(){
    console.log(3);
});

bar();

Gemäß der Analyse im vorherigen Abschnitt geben Sie zuerst den globalen Kontext ein, führen Sie ihn zu foo() aus und geben Sie die foo-Kontextumgebung ein Die foo-Kontextumgebung wird aus dem Stapel entnommen, an console.log(1) ausgeführt und an den geplanten Verarbeitungsthread des setTimeout übergeben. und die Konsole gibt 2 aus; der Foo-Kontext wird angezeigt. Warten Sie, bis der Browser-Thread die Ausführung beendet hat, und geben Sie die bar()-Rückruffunktion nach der Ausführung an die aktuelle console.log(2)-Aufgabenwarteschlange zurück Wenn festgestellt wird, dass der Stapel leer ist, führt die JS-Engine des Browsers eine Schleife aus und entfernt den Kopf der Ereigniswarteschlange in den JS-Ausführungsstapel und die Konsole gibt 3 aus; die Ereigniswarteschlange ist leer und der globale Kontext wird aus dem Stapel entfernt. setTimeoutcb()Das Obige ist der Ereignisschleifenmechanismus der JS-Engine, ein Mechanismus zur Erzielung einer asynchronen Implementierung. Es handelt sich hauptsächlich um Browser-Thread, Aufgabenwarteschlange und cb()JS-Engineconsole.log(3). Daher können wir sehen, dass die asynchrone Anforderung von JS darauf angewiesen ist, dass der Browser seiner laufenden Umgebung das Ergebnis verarbeitet und zurückgibt. Darüber hinaus erklärt dies auch, warum das

dieser Rückruffunktionen auf

verweist, da diese asynchronen Codes im globalen Kontext ausgeführt werden. Nachwort: Ich weiß nicht, ob ich es richtig verstanden habe und ich weiß nicht, ob ich es klar erklärt habe oder nicht. Wenn es Unangemessenheiten gibt, weisen Sie bitte darauf hin. Referenzmaterialien: thiswindowJavaScript: Synchronisation, Asynchronität und Ereignisschleife (Ereignisschleife) gründlich verstehen

Ich frage mich immer noch, was Parallelität ist und Parallelität?

  • IMWeb Community Browser-Prozess? Faden? Blödsinn, ich kann den Unterschied nicht erkennen!

  • Eingehende Analyse von Javascript als Single-Threading

  • Eine kurze Einführung in JavaScript-Single-Threading und Browser-Ereignisschleife

  • AlloyTeam [Weiter zur Javascript-Reihe] Lassen Sie uns über das Ereignisschleifenmodell von setTimeout sprechen

  • Prinzipien der asynchronen JavaScript-Programmierung von Moustache Brother

  • Ruan Yifeng JavaScript läuft Detaillierte Erklärung des Mechanismus: Reden wir noch einmal über Event Loop

  • [Kommentar von Pu Ling] Detaillierte Erklärung des JavaScript-Betriebsmechanismus: Reden wir über Event Schleife

    noch einmal
  • Philip Roberts: Hilfe, ich stecke in einer Ereignisschleife fest.

  • Philip Roberts: Was zum Teufel ist eigentlich die Ereignisschleife?

  • jquery中Ajax的异步和同步

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des JavaScript-Funktionsmechanismus und konzeptionelle Analyse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn