Transkripte
1. JavaScript Critical Concepts Einführung: Willkommen in diesem Abschnitt über kritische Konzepte in JavaScript. In diesem Abschnitt
werden wir uns mit den meiner
Meinung nach
kritischen Konzepten der Sprache
und der
Funktionsweise von JavaScript befassen kritischen Konzepten der Sprache
und der
Funktionsweise . Nun möchten einige von Ihnen vielleicht zwei Abschnitte
voranbringen, die sich mehr auf den
Sprachaspekt von JavaScript konzentrieren. Aber ich möchte die Patienten dringend bitten, diese Konzepte sind von entscheidender Bedeutung. Wenn Sie nun
in diesem Abschnitt beginnen, scheinen
einige der Konzepte einfach zu sein, weil sie es sind. Aber selbst wenn Sie schon Weile mit
JavaScript
arbeiten, werden Sie sicher etwas
lernen. Also bleib dabei. Warum sind diese
Konzepte von entscheidender Bedeutung? Warum ist es wichtig zu verstehen,
wie die Sprache funktioniert? Denn ein wichtiger Teil des Verständnisses
eines guten Entwicklers besteht darin, zu wissen, warum Sie bestimmte Dinge
tun. Das y
ermöglicht es, Muster oder Code an
Ihre spezifischen Bedürfnisse anzupassen. Sie erleichtern
kritisches Denken. Und diese Konzepte liefern
das Warum für viele Dinge, die wir in JavaScript
tun und über die wir später sprechen
werden. In
der Tat möchten
Sie im Rahmen späterer Abschnitte möglicherweise zurückkommen und einige dieser Themen
erneut behandeln, z. B. die Ereignisschleife beim Umgang mit asynchronem Code. Daher ist es wichtig,
einige Zeit damit zu verbringen , über
die JavaScript-Engine,
den Call-Stack, den Speicher-Heap zu sprechen . Die Tatsache, dass JavaScript Single Thread
ist, die Laufzeitumgebung
und die Ereignisschleife. Also lasst uns hineinspringen.
2. Die JavaScript: Damit wir JavaScript
nutzen können, benötigen
wir eine Umgebung, in der es ausgeführt wird. Jetzt benötigt JavaScript
nicht viele Tools, um Code zu schreiben. Tatsächlich können wir einfach
einen einfachen Texteditor öffnen und
anfangen, JavaScript zu schreiben. Damit dieser Code jedoch
Sinn macht oder irgendetwas tun kann, müssen
wir den
Code für
eine
JavaScript-Laufzeitumgebung verfügbar machen . Jetzt gibt es zwei
Haupt-Laufzeitumgebungen, die
den Großteil der Verwendung von JavaScript
ausmachen, den Browser und NodeJS. So können wir JavaScript
ausführen lassen und eine Aufgabe entweder über
den Browser oder den Knoten ausführen. Nun, diese beiden Umgebungen sind nicht die einzigen, die
wir verwenden könnten, aber sie sind die wichtigsten
und am weitesten verbreiteten. Jetzt gibt es einige Ähnlichkeiten zwischen Node und Browsern, und dann gibt es
einige Unterschiede. Lassen Sie uns kurz darüber sprechen. Erstens sind sowohl ein Browser als auch
ein Knoten einfach eine Anwendung. In jedem Fall müssen sie auf Ihrem
Computer
installiert sein , um sie verwenden zu können. Wir haben Node
früher im Kurs installiert. Wenn ich einen Browser starte, in diesem Fall Chrome, starte
ich diese
Anwendung von meinem Computer aus. Jetzt gilt dasselbe mit node. Wir benutzen es einfach anders. Wir müssen es über das
Terminal oder die Eingabeaufforderung verwenden. Und wir
verwenden normalerweise keine GUI-Schnittstelle. Zum Beispiel kann ich auf den
Knoten zugreifen, indem ich das eintippe. Und jetzt habe ich eine Node Prompt. So verwende ich node. Eine weitere Ähnlichkeit besteht darin,
dass diese Anwendungen, also sowohl der
Browser als auch der Knoten, mit
derselben Computersprache geschrieben wurden. Im Fall von Chrome und den meisten Browsern ist
der Kern dieser Anwendung in C plus plus geschrieben. Die GUI ist normalerweise eine
andere Sprache, aber der Kern ist C plus plus. Jetzt
ist der Kern von NodeJS auch in
C plus plus mit
etwas
JavaScript-Code geschrieben , der
als Wrapper für einige
der von uns verwendeten Befehle fungiert . Der Code. Diese beiden
Anwendungen sind im Browser geschrieben und Node
ist sehr ähnlich, aber das macht
es uns nicht möglich, JavaScript in jeder
dieser Umgebungen zu verwenden. Damit eine
JavaScript-Laufzeitumgebung die Verwendung von JavaScript erlaubt, benötigt
sie etwas, um die Sprache zu
interpretieren, das JavaScript
zu lesen und für den Computer zu
übersetzen. Dieses sehr wichtige Teil heißt JavaScript-Engine. Sowohl ein Browser als auch ein Knoten benötigen eine JavaScript-Engine
, um JavaScript verwenden zu können. Jetzt ist die JavaScript-Engine nur noch ein Teil der
gesamten Anwendung. Es gibt viele
andere Teile einem Browser und es gibt viele andere Teile,
die geknotet werden müssen. Werfen wir einen
Blick auf ein Diagramm, das die
Laufzeitumgebung für unseren Browser
veranschaulicht. Dies sind alle
Teile, über die wir sprechen
werden, weil wir mit ihnen
interagieren, wenn wir
JavaScript im Browser verwenden. Wenn dieses Ganze also den Browser
darstellt
und was er enthält, können
wir sehen, dass es Dinge
gibt, die nicht von der JavaScript-Engine
getrennt sind , die hier oben dargestellt wird. Manchmal machen wir
Dinge in JavaScript , die Teile der
Browseranwendung verwenden , die nicht Teil der JavaScript-Engine sind. Nun sind diese anderen Teile oder
Teile einige der Dinge,
die sich zwischen
einem Browser und einem bekannten
unterscheiden . In einem Browser interagieren
wir beispielsweise mit dem DOM, das hier in den Web-APIs
ausführlich dargestellt wird. Nun, das machen
wir in Node nicht. Es gibt kein DOM, das Teil von Node
ist. Bekannt macht es jedoch möglich , andere Arten von Aufgaben zu erledigen. Aufgaben, die auf einem Server
erforderlich sind, z. B. das Schreiben einer Datei auf eine
Festplatte oder das Starten eines Servers. Das sind Dinge, die wir in einem Browser nicht tun
können. Es gibt also einige Unterschiede. Schauen wir uns ganz schnell einen anderen
Unterschied an. Also hier in einem Browser, wenn ich die Konsole öffne, kann
ich Fenster anzeigen. Dadurch wird das Fensterobjekt angezeigt. Dies ist die globale Umgebung , in der wir Code schreiben. Wenn wir schreiben,
ist JavaScript im Fenster. Und mit dem Fenster ist viel
verbunden, was wir nutzen können. Jetzt hat der Knoten kein Fenster. Wenn wir hier Fenster eingeben, nicht abgefangene Referenz, ist unser
Fenster nicht definiert. Wir können jedoch global tippen. Und wir erhalten Informationen
über Global. Und das wäre das Äquivalent zu Window auf der Browserseite. Jetzt
wird es natürlich Ähnlichkeiten geben. Zum Beispiel können Sie
setTimeout hier in global sehen. Settimeout ist auch
im Browser verfügbar. Sie können sehen, dass es nicht in
der JavaScript-Engine ist. Es ist eigentlich Teil
der Web-API. Das Gleiche gilt für Node. Es ist kein Teil der
JavaScript-Engine, aber wir haben Zugriff darauf. Und wir können hier so etwas
wie console.log machen. Und genau wie wir
es in einem Browser tun können. In den nächsten
Themen werden
wir nun über diese verschiedenen Teile eines Browsers
sprechen , da sie für das Verständnis
von
entscheidender Bedeutung sind. Um effektiv
schreiben zu können, JavaScript. Node hat auch zusätzliche Teile, aber wir werden uns
hauptsächlich auf den Browser konzentrieren. Zunächst werden wir über die JavaScript-Engine
sprechen.
3. Verständnis der JavaScript-Engine: Einfach ausgedrückt ist die
JavaScript-Engine ein Programm, das
JavaScript-Code ausführt. also unser Diagramm ansehen Wenn wir uns also unser Diagramm ansehen und etwas JavaScript-Code haben, ist
die
JavaScript-Engine verantwortlich. Es ist das einzige Stück, das weiß,
was mit dem Code zu tun ist. Es übersetzt es in etwas, das der
Computer verstehen kann. Anfängliche JavaScript-Engines waren
schon früh Interpreter, was bedeutet, dass sie
den
JavaScript-Code Zeile für Zeile verarbeiten und in Bytecode
konvertieren, damit er ausgeführt werden konnte. Interpreter werden beendet
, um den Code auszuführen
, was
in der Browserumgebung benötigt wurde . können sie jedoch insgesamt
langsamer sein Im Vergleich zum Kompilieren des Codes können sie jedoch insgesamt
langsamer sein. Kompilierter Code
konvertiert das Programm in Maschinencode, sodass
es optimiert ausgeführt wird. Die neuesten JavaScript-Engines
sind viel optimierter. Sie verwenden eine Kombination aus einem Interpreter und Just-in-Time, Compilation oder JIT-Compiler
, um den Code zu optimieren. Dies bringt das Beste
aus beiden Welten. Die Kompilierung von Jit nimmt kalt , kann optimiert werden
und kompiliert sie. Wenn beispielsweise ein Teil
des Codes viel ausgeführt wird, kann
er
zu Maschinencode kompiliert werden. Und wenn dieser
Code dann ausgeführt wird, ist
er optimiert und
daher schneller. Jetzt gibt es eine Reihe
von JavaScript-Engines. Derjenige, der
wahrscheinlich am bekanntesten ist, ist der V8-Motor. Dies ist die Engine
, die im
Chrome-Browser
und auch im Node verwendet wird. Diese Engine wurde von
Google für Chrome
mit C plus plus geschrieben . Und es ist Open Source. Es ist wahrscheinlich die
bekannteste Engine da sie bei die Geschwindigkeit
vorhandener JavaScript-Engines verbessert hat. Google nutzte zu dieser Zeit
JavaScript, um
einige ziemlich erstaunliche
Dinge zu tun . Denken Sie an die
verschiedenen Google-Apps mit JavaScript
geschrieben wurden. Jedenfalls wollten sie
, dass es leistungsfähiger wird. Also haben sie die V8-Engine geschrieben
, um genau das zu erreichen. Andere JavaScript-Engines
folgten diesem Beispiel, um ihre Engines ebenfalls leistungsfähiger zu
machen. Diese
Leistungsverbesserung ist wichtig, um sich dieser Idee bewusst zu sein einen JIT-Compiler
mit einem Interpreter zu
verwenden ,
um den Code zu optimieren. Der Grund dafür ist
wichtig, weil wir über das Schreiben von Code auf
bestimmte Arten
sprechen
, um die Leistung zu steigern oder Dinge in unserem Code
zu vermeiden , die die Leistung
beeinträchtigen könnten. Oft hat es damit zu tun, wie
die JavaScript-Engine mit wie
die JavaScript-Engine dem Code
umgeht und ihn optimieren
kann. Hier sind einige andere
JavaScript-Engines Sie möglicherweise gestoßen sind. Wir haben V8 bereits erwähnt
, dass es sich um Open Source handelt, das von Google entwickelt wurde. Es wird in Chrome und NodeJS verwendet. Klammeraffe. Dies war die erste
JavaScript-Engine und wird heute in Firefox verwendet. Und übrigens wurde die erste JavaScript-Engine von
Brendan Eich geschrieben , als er JavaScript
erfand, und wie es in der Geschichte heißt, tat es in zehn Tagen. Nun,
JavaScript-Kern, das ist auch Open Source und wurde von Apple für Safari
entwickelt. Das ist also die Engine
, die Safari verwendet. Ein anderes, das wir
wahrscheinlich erwähnen sollten, ist Chakra. Und das wird
in Microsoft Edge verwendet. Also Microsofts
JavaScript-Engine. Nun, mit all diesen verschiedenen JavaScript-Engines in
verschiedenen Browsern, woher wissen wir, dass
der JavaScript-Code, den wir schreiben, in jedem Browser auf die gleiche
Weise funktioniert. Zu Beginn der Geschichte von JavaScript war
dies ein echtes Problem. Es gab Unterschiede. In jenen Tagen. Wir haben viel
Zeit damit verbracht , uns Gedanken über
Unterschiede in den Browsern zu machen Bibliotheken wie
jQuery helfen bei der Lösung dieses Problems und wurden aus diesem Grund sehr
beliebt. Aufgrund
dieser Unterschiede musste
es nun
einen Standard geben, und hier
kommt das Acme-Skript ins Spiel. Dies ist ein Standard, dem
JavaScript folgt. Ein AGMA-Skript ist eine Spezifikation, der jetzt alle
JavaScript-Engines folgen. Dies ermöglicht mehrere
unabhängige Implementierungen, stellt
jedoch sicher, dass unser
Code gleich funktioniert. Wenn also Änderungen am Skriptstandard vorgenommen
werden, müssen
die Indianer aktualisiert werden,
um diese Änderungen zu unterstützen. Manche Updates sind
schneller als andere. Und deshalb haben wir
Websites wie diese. Kann ich.com verwenden, das uns
sagt, welche Browser
bestimmte Implementierungen unterstützen? So können wir in diesem Beispiel den Verlauf
verschiedener Browser sehen und wann sie angefangen haben , ES-Module
zu
unterstützen. Das ist auch der Grund, warum
wir Transpiler verwenden. einem Transpiler wie Babble können
Sie Code mit
dem leichtesten
Ekman-Skriptstandard schreiben , gibt dann
aber
JavaScript-Code auf einen älteren Standard aus. Also eine frühere Form
von JavaScript, die ältere Browser-Engines ausführen können. Dies kann auch als Compiler bezeichnet
werden, da Sie
Code
technisch gesehen in ein anderes Formular und eine
ältere Version von JavaScript kompilieren . Ordnung, das reicht also
über JavaScript-Engines. Jetzt müssen wir mehr
ins Detail gehen und
über den Heap und den Call
Stack innerhalb der Engines sprechen . Diese beiden Dinge werden häufig beim
Codieren in JavaScript
verwendet, auch wenn Sie vielleicht nichts davon gewusst
haben.
4. Der Speicher-Heap und der Call: Wir werden uns nun mit zwei Funktionen der JavaScript-Engine
befassen ,
die wichtig zu verstehen
sind, Speicher-Heap und den Aufruf-Stack. Diese werden während der gesamten
Codeausführung verwendet. Zuerst beschreibe ich jeden einzelnen von ihnen und dann werden
wir sie in
Aktion sehen , um besser zu verstehen, wie sie an der Codeausführung
beteiligt sind. Jetzt
hat der Speicher-Heap, wie der Name schon sagt, wie der Name schon sagt, mit der
Speicherzuweisung zu tun. Immer wenn Sie eine
variable Objektfunktion definieren, etwas Ähnliches in Ihrem Code, muss
es einen
Ort geben, an dem sie gespeichert werden kann. Also wie diese Variablen hier im
Speicher-Heap gespeichert
würden. Immer wenn eine Deklaration wie diese
gefunden wird, wird
der Wert
in den Speicher-Heap gelegt, und dann wird der Speicherort dieses Werts
in der Variablen platziert. Wann immer der Code
diesen Wert benötigt oder die Funktion
oder was auch immer gespeichert ist, verwendet
er den
Speicherort, um ihn nachzuschlagen. Jetzt hat der Speicher eine
begrenzte Menge an Speicher, sodass komplexe Programme, die viele Variablen und
verschachtelte Objekte
haben , diesen Speicher zerbrechen können
. Die JavaScript-Engine versucht, mehr Speicher
verfügbar zu machen, indem sie Daten
aus dem
Programm löscht, die ihrer Meinung nach
nicht mehr erforderlich sind. Dieser Vorgang wird
Garbage Collection genannt. Es gibt Dinge, die Sie als Programmierer tun
können um bei der Garbage-Collection zu helfen. Und es gibt Dinge, die Sie
tun könnten, die dies behindern könnten. Wir werden uns
das im Thema
Garbage Collection genauer ansehen. Aber jetzt sprechen wir
über den Call Stack. Immer wenn wir Code ausführen, wird
der Aufruf-Stack verwendet. Es ist einfach ein Ort im Speicher, der die
ausgeführte Funktion und die Funktionen
, die danach
ausgeführt werden,
verfolgt ausgeführte Funktion und die Funktionen . Also die Reihenfolge, in der diese
Befehle ausgeführt werden. Jetzt wird jede Funktion über der
vorherigen Funktion
platziert. Die erste Funktion
in befindet sich also am unteren Rand
des Aufruf-Stacks. Und wenn dann andere
Funktionen aufgerufen werden, werden
sie darauf platziert. Der Call-Stack folgt also einem
First-In-Last-Out-Ansatz. Sobald die Funktion oder der Befehl abgeschlossen ist, wird sie aus
dem Aufruf-Stack entfernt. Wie Sie dem Diagramm
entnehmen können,
ist jetzt nur ein einziger
Aufruf-Stack dargestellt. Die JavaScript-Engine verfügt nur über einen Aufruf-Stack, um mit ausgeführten
Befehlen umzugehen. Das liegt daran, dass JavaScript ein Single-Thread
ist, ein Begriff, von dem Sie vielleicht gehört haben. Jetzt bedeutet ein einzelner Thread
, dass die JavaScript-Engine jeweils
nur einen Teil
des Programms ausführen kann . Der Aufruf-Stack
behandelt also jeweils einen Befehl. Und als Ergebnis davon ist
JavaScript synchron. Befehle können jeweils nur einzeln
ausgeführt werden. Sie können wahrscheinlich ein
mögliches Problem damit sehen. Was ist, wenn wir
eine Funktion aufrufen, deren Ausführung eine lange Zeit benötigt? Wie können wir verhindern, dass
dadurch anderer Code blockiert wird? Zum Beispiel möchten wir, dass ein
Benutzer
auf eine Schaltfläche klicken kann und nicht zwei Sekunden
warten
muss, bis etwas JavaScript beendet ist, bevor es auf diese Schaltfläche
reagieren kann. Nun werden wir untersuchen,
wie dies gehandhabt wird und wie die JavaScript-Engine damit umgeht , wenn wir
über die Ereignisschleife sprechen. Und das ist auch der Grund, warum
es wichtig ist, asynchrone
JavaScript-Muster
in JavaScript zu
verstehen . Und das ist einer
der kritischen Aspekte , mit denen wir uns
in diesem Kurs befassen. Wie Sie sehen können, haben
wir in unserem Diagramm einen sehr einfachen Code. Lassen Sie uns das mit
dem Speicher-Heap
und dem Aufruf-Stack durchgehen dem Speicher-Heap
und dem Aufruf-Stack veranschaulichen, wie diese
beim Durchlaufen des Codes verwendet werden. Im Grunde
deklarieren wir zwei
Variablen, a und B. Dann haben wir eine
Funktion deklariert. Und dann rufen wir
diese Funktion hier auf. Innerhalb der Funktion rufen
wir Console Log auf. Wir rufen setTimeout auf und übergeben
eine Funktion an setTimeout. Die Zeit dafür
beträgt 0 Millisekunden. Und dann rufen wir erneut
Console Log auf. Also lasst uns das durchgehen. Zuerst haben wir die
Variablendeklarationen. Und so wird jeder
von ihnen
auf den Speicherhaufen gelegt. Es gibt 1 Sekunde. Jetzt gibt es keine
bestimmte Reihenfolge wie sie im Heap platziert werden. Sie benötigen lediglich einen Verweis darauf, wo sich dieser Wert befindet. Dann haben wir unsere Funktion. Und das muss auch auf den Haufen
gelegt werden . Und da haben wir
das dem Speicher-Heap hinzugefügt. Wenn nun Variablen innerhalb
dieser Funktion
deklariert wären , müssten
diese dort platziert
werden. Oder wenn darin Funktionen
deklariert sind, wenn sich andere Dinge
darin befinden , die in den Speicherheap
gelangen müssen, müsste
das passieren. Aber jetzt begegnen wir uns. Der Aufruf von helloworld für diese Funktion.
Wir berufen uns darauf. Die JavaScript-Engine schnappt sich
diesen Code also von ihrem
Speicherort und kann
ihn dann mithilfe des Aufruf-Stacks ausführen . Die
Hello-World-Funktion wird also auf
dem Aufruf-Stack platziert , der
anzeigt, wo wir uns innerhalb
der Codeausführung befinden. Moment befinden wir uns also innerhalb
der Funktion helloworld. Wir kommen zum ersten
Befehl da drin, und das ist ein Aufruf
von console.log. Also haben wir unser aufrufendes
Konsolen-Punktprotokoll und das wird
auf den Aufruf-Stack gesetzt. Jetzt können wir diesen Befehl ausführen. Sobald dieser
Befehl abgeschlossen ist, wird
er aus
dem Aufruf-Stack entfernt und wir können weitermachen. Und wir können timeout setzen und setTimeout wird dem Aufruf-Stack hinzugefügt
. SetTimeout
ist jedoch Teil der Web-API, wie Sie hier sehen können. Damit muss JavaScript also nichts anfangen. Also wird es im Grunde genommen los. Es sendet es an den
Browser und sagt: Hier muss ich das setTimeout
aufrufen. Hier sind die Informationen. Du machst weiter und
kümmerst dich darum. Und dann vergisst die
JavaScript-Engine es an diesem Punkt, die Web-API, wir richten einen Timer für
dieses setTimeout ein und es wird alles
verarbeiten, was mit setTimeout behandelt werden muss . Aber zu diesem Zeitpunkt hat
die JavaScript-Engine es einfach vergessen. Es macht sich
darüber keine Sorgen mehr. Es geht einfach weiter
zum nächsten Befehl, bei dem es sich um einen anderen
Kollegen handelt, console.log. Und so wird das
zu unserem Call-Stack hinzugefügt. Wir können uns sofort darum kümmern
. Wir senden eine Nachricht
an die Konsole, die zufällig Welt ist. Und dann wird das
aus dem Call-Stack entfernt. Und dann sind wir an diesem Punkt am Ende
der
Hello-World-Funktion. Und so wird das
aus dem Call-Stack entfernt. Jetzt können Sie sehen, wie der Call-Stack mit einer
Reihe von Dingen
aufgebaut werden könnte . Wenn wir Funktionen
innerhalb anderer Funktionen aufgerufen hätten. Und je mehr wir solche verschachtelten
Funktionen haben, desto mehr Dinge
werden dem Aufruf-Stack hinzugefügt. Und wir werden
auf diesem Call Stack aufbauen. Denn bis eine
Funktion zurückkehrt, bis sie abgeschlossen ist,
kann sie nicht
aus dem Aufruf-Stack entfernt werden. Jetzt mit dieser ganzen
Illustration habe ich setTimeout dort drüben gelassen und gesagt, die
JavaScript-Engine habe es einfach vergessen. Nun, wir werden darüber sprechen
, wenn wir zum Thema in der Ereignisschleife kommen,
denn in Wirklichkeit sind es die Ereignisschleife und
die Nachrichtenwarteschlange,
die sich
damit befassen, die sich mit diesen
Web-API-Elementen befassen. Also werden wir das
in einem anderen Thema diskutieren. Bevor wir jedoch
zum nächsten Thema übergehen, möchte
ich
etwas ansprechen, das wir mit dem Aufruf-Stack finden können , das Stack Overflow
heißt. Und dies ist eine
Bedingung, auf die Sie möglicherweise bei Ihrer Codierung gestoßen sind. Dies tritt auf, wenn der
Aufruf-Stack voll ist,
weil er
Befehle nicht entfernen kann und weitere hinzugefügt werden. Ich erwähnte, dass
verschachtelte Funktionen Aufruf-Stack viel hinzufügen
könnten. Nun, es dauert ziemlich
viel, bis sich
der Aufruf-Stack füllt. Aber wenn es voll ist, verursacht
es einen Fehler. Jetzt können wir das ziemlich
einfach mit einem rekursiven Aufruf simulieren . Jetzt ist Rekursion einfach, wenn sich
eine Funktion selbst aufruft. Und es gibt einige
Situationen, in denen dies ein vorteilhaftes
Muster in JavaScript ist. Aber ich möchte
Ihnen zeigen,
wie sich das auf den Stack auswirkt. Also lasst uns weitermachen und
eine Funktion einrichten , die dies
veranschaulicht. Diese JavaScript-Datei ist an die HTML-Datei
angehängt. Dieser hier, den wir uns zuvor
angesehen haben. Ich setze einfach eine Funktion darauf und nenne es sich selbst ramus. Schau was passiert. Also nenne ich es Rekursion. Es ist nicht nötig, es so
zu nennen, aber ich werde das tun, weil
ich es nenne. Und dann setze ich die Zahl,
die übergeben wird, gleich
sich selbst und sich selbst, so etwas Einfaches. Und dann passiert hier
die Rekursion. Wir rufen uns von innen heraus an. Denken Sie also darüber
nach, was das bewirken wird. Der Call-Stack. Wir werden die
Rekursion aufrufen , um die
Rekursion auf dem
Aufruf-Stack
zu platzieren , um zu dieser Zeile zu gelangen. Und die Rekursion wird
erneut aufgerufen, aber die Funktion wurde
noch nicht abgeschlossen, sodass sie nicht
aus dem Aufruf-Stack entfernt wurde. Ein weiterer Aufruf davon
wird dem Aufruf-Stack hinzugefügt. Und so fügt es
dem Aufruf-Stack immer wieder Rekursion
hinzu , bis
es bis zu
dem Punkt aufgebaut ist, an dem es nicht mehr hinzugefügt werden
kann. Und hier bekommen
wir den Stack-Überlauf. Lassen Sie mich weitermachen und mich darauf berufen. Ich werde die Nummer eins weitergeben. Das sparen wir uns. Jetzt, da ich das gerade an diese HTML-Datei
angehängt
habe, werde ich
das einfach aktualisieren und sehen, was passiert. Lass uns die Konsole öffnen
und sehen, was wir dort haben. Wir haben einen nicht gefangenen Luftbereich. Unsere maximale Call
Stack-Größe wurde überschritten. Das ist die Luft, die
wir erhalten würden. Wenn wir einen Stack-Überlauf hätten. Die maximale
Call-Stack-Größe wurde überschritten, und genau das erreichen
wir. Dies ist ein einfach zu
lösendes Problem. Alles was wir tun müssen,
ist sicherzustellen, dass die Funktionen
irgendwann
abgeschlossen werden und dass sie zurückkehren. Und dann kann es
sie aus dem Call-Stack entfernen. Entferne sie schließlich alle
aus dem Skull Call Stack. Schauen wir uns an
, wie das gemacht werden könnte. Nehmen wir an, wenn die Zahl größer ist als und ich werde hier nur eine große Zahl
eingeben. Ich habe keine Ahnung, wie groß
es sein wird, aber wenn es größer ist, melde ich mich einfach bei der Konsole an. Ich möchte sehen, wie
groß die Zahl ist, nur zum Spaß. Und dann kehre ich zurück. Also hier
kehren wir von dieser Funktion zurück. Damit die
Funktion abgeschlossen ist, kehren wir hierher zurück. Das wird es nicht wieder tun. Und es wird die
Funktion vervollständigen, in der wir uns befinden. Und dann wird es den Aufruf-Stack
abwickeln, jede dieser Funktionen. Wir werden endlich
zurückkehren können , weil es
das Ende der Funktion erreicht. Und so ruft die Tatsache, dass das letzte Mal, wenn wir das nennen
, wo die Zahl größer ist als
diese, eine Rückkehr erzwingt, keine andere. Und so können auch all die anderen
, die sich im Call-Stack , abgeschlossen werden. Und dann bekommen wir
diesen Stack-Überlauf nicht. Ordnung, schauen wir uns
das noch einmal an. Ich werde mich hier erfrischen. Ich möchte mich daran erinnern, dass es
nicht größer wird, wenn ich es
nicht wieder eingebe, wenn
ich diese Funktion aufrufe. Also möchte ich sichergehen, dass
es größer wird. Da haben wir's. eine sehr große Anzahl kommt
eine sehr große Anzahl heraus und wir bekommen
keinen Stack-Überlauf mehr ,
weil wir zurückkehren konnten. Und dann wickeln Sie alle Funktionsaufrufe ab
, die sich im Stack befinden. Darauf beziehen wir uns also, wenn wir über
StackOverflow sprechen. Ordnung, gehen wir
zum nächsten Thema über.
5. Verständnis der Müllsammlung: Im vorherigen Thema haben wir die Garbage-Collection
im Zusammenhang mit
dem Speicher-Heap erwähnt . In einer Sprache wie C müssen
wir Speicher zuweisen
und freigeben. In JavaScript ist es nicht so, aber es muss immer noch
einen Mechanismus geben, um Speicher
zurückzugewinnen. Wir haben also nicht zu wenig
Speicher und wir stürzen das System ab. Javascript kümmert
sich für uns um die Rückgewinnung von Speicher. Sobald eine Information, ein Objekt oder eine Variable, aus dem Zusammenhang gerissen
ist und
nicht mehr verwendet wird. Sein Speicher wird zurückgewonnen, sodass er wiederverwendet werden kann. Dies wird
Garbage Collection genannt. Schauen wir uns an
, wie das im Motor funktioniert. Garbage-Collection
findet im Speicher-Heap statt und verwendet einen manchmal so genannten
Mark-and-Sweep-Algorithmus. Es bestimmt die
Objekte, die
sicher aus
der Speicherwärme gelöscht werden können , indem
bestimmt wird , welche Dinge erreichbar und welche nicht erreichbar
sind. Und dann durchquert es
diejenigen, die nicht erreichbar sind. Sie werden weggefegt und
diese Erinnerung wird zurückgewonnen. Schauen wir uns
an, wie es funktioniert. Jetzt
beginnt der Garbage Collector mit dem Root- oder Global-Objekt und wechselt zu den Objekten, auf die von ihnen verwiesen wird. Und es bewegt sich von einem
Objekt zum anderen identifiziert Dinge, auf die
sich etwas anderes bezieht. Im Grunde sind die Dinge,
die erreichbar sind, die Dinge, die nicht
erreichbar sind, jetzt definiert. Und dann alles
, was nicht erreichbar ist, wir sehen jetzt ein paar Dinge, die nicht miteinander verbunden oder nicht erreichbar
sind. Alles, was
nicht erreichbar ist, wird gelöscht. Es geht durch und
fegt die ab. Sie sind weg. Diese Erinnerung kann jetzt zurückgewonnen und
für etwas anderes verwendet werden. Wie Sie
in unserer Erklärung bemerkt haben, darf die
Reihenfolge, in der Informationen
freigegeben und zurückgefordert werden , nicht mit etwas
verbunden sein , das
derzeit im Programm vor
sich geht , das nicht erreichbar ist. Es ist zwar möglich unsere Codierung verhindert, dass Dinge
zurückgefordert werden, obwohl wir sie
nicht mehr verwenden. Dies wird als Speicherleck bezeichnet. Speicherlecks sind Teile des
Speichers, die die Anwendung in der Vergangenheit
benötigt
und verwendet hat und die nicht mehr benötigt werden, aber ihr Speicher wird noch nicht an den Speicherpool
zurückgegeben. Auch wenn die
Müllabfuhr für uns abgewickelt wird. Wie wir gesehen haben,
müssen wir bei
der Speicherverwaltung immer noch vorsichtig sein. Speicherlecks können dazu führen, dass
JavaScript-Programme fehlschlagen indem
der gesamte verfügbare Speicher verbraucht wird. Schauen wir uns einige allgemeine Dinge an , die zu Speicherlecks führen können. Also zuerst globale Variablen. Wenn Sie weiterhin
globale Variablen erstellen, bleiben
sie während
der gesamten Ausführung des Programms erhalten, auch wenn sie nicht benötigt werden. Wenn es sich bei diesen Variablen um
tief verschachtelte Objekte
handelt, kann viel Speicher verschwendet werden. Event-Listener
, die nicht mehr benötigt werden, werden nicht entfernt. Als ein Beispiel dafür, wie diese
besondere Sache passieren kann. Sie könnten viele
Event-Listener
für eine bestimmte
Seite oder einen bestimmten Ort erstellen . Und wenn der
Benutzer das hinter sich lässt, wo diese Ereignis-Listener lang
sind, werden sie nicht mehr benötigt. Sie als Programmierer sollten sie
nicht entfernen. Sie sind immer noch da. Sie belegen immer noch Speicherplatz, insbesondere für die Objekte
, mit denen verknüpft ist. Also etwas, dessen man sich bewusst sein sollte. Der dritte Punkt, unklare
Zeitintervalle. Das eingestellte Intervall ist ein
gutes Beispiel dafür. Und wenn Sie set interval nicht
verwendet haben, können Sie
im Grunde genommen Code
basierend auf einer festgelegten Zeit immer wieder ausführen . Schauen wir uns nun ein sehr
kurzes Beispiel dafür an. Ich
rufe einfach set interval auf. Und das eingestellte Intervall nimmt als
ersten Parameter eine Funktion an. Dies ist eine Callback-Funktion. Jedes Mal, wenn das
Intervall abläuft, die Zeit, die wir eingeben ruft
die Zeit, die wir eingeben
, diese
Callback-Funktion auf. Also werde ich hier eine Funktion
einrichten. Und dann ist der zweite
Parameter die
Zeitspanne in Millisekunden, in der jedes Intervall stattfindet. Also alle 200 Millisekunden wird
diese Funktion aufgerufen, okay? Nun, wo dies
zu einem Problem werden kann, sagen wir hier, beziehen
wir uns auf die
Anzahl der Objekte. Diese Objekte sind,
werden dort referenziert. Manchmal wird so
etwas
mit Animationen oder
ähnlichem gemacht . Wenn dies jedoch nie gelöscht wird, wenn dieses festgelegte Intervall nicht gelöscht
wird, sind diese Verweise
offensichtlich immer noch gültig. Und so wird es niemals in der Lage
sein
, diesen Speicher freizugeben , selbst wenn er nicht
mehr verwendet wird. Ein besserer Ansatz für das Problem des
gesetzten Intervalls besteht also eine ID zu
deklarieren, und wir setzen diese
gleich setInterval, wodurch eine ID hier
platziert wird . Wenn wir dann fertig sind, sollten
wir sicherstellen, dass wir klares Intervall mit dieser
ID haben, ungefähr so. Okay, noch eine Sache, die
wir erwähnen müssen, und das sind entfernte DOM-Elemente. Wenn Sie in Ihrem Programm
Elemente aus dem DOM entfernen. Diese Elemente
sind jedoch immer noch Referenz, z. B. bei einem Event-Listener. Wir haben früher darüber gesprochen, oder auf andere Weise, der
Speicher wird nicht freigegeben. Etwas anderes, auf das Sie achten sollten. Nun werden wir
einige dieser und andere
Stellen im Kurs erneut besuchen ,
damit Sie sich an
Best Practices erinnern können, um Speicherlecks zu
verhindern. All diese Dinge, über die wir
gesprochen haben, können
sich summieren und die Speicherlecks werden immer mehr
Speicher beanspruchen. Wenn Ihr Programm lange genug
läuft, kann
es aufgrund von Speichermangel fehlschlagen
. Auch wenn es nicht herunterfällt, sollten Sie darauf achten,
Speicherlecks zu vermeiden und sich nicht nur auf die Garbage Collection
verlassen
, um den Tag zu retten. Ordnung, gehen wir
zum nächsten Thema über.
6. Entfernen von Event zur Unterstützung bei der Müllsammlung: In diesem zweiten
Thema zur Garbage Collection möchte
ich einige der
Techniken erläutern, die für die
im vorherigen Thema erwähnten Browser
spezifisch sind . Insbesondere
werde ich darauf eingehen, wie
Ereignis-Listener und JavaScript entfernt werden. Nicht alle JavaScript-Entwickler sind mit dieser Funktion vertraut, aber sie ist wichtig, wenn es
um Garbage Collection geht. Also wollte ich es hier einfügen. Wenn Sie jetzt
für den Browser codieren, arbeiten
Sie
mit der Morgendämmerung. Das DOM ist die Abkürzung für
Document Object Model. Es ist einfach eine
Schnittstelle, mit der JavaScript den Inhalt, die
Struktur und den Stil
des HTML-Dokuments
bearbeiten kann. Das HTML-Dokument wird
mithilfe von Knoten und Objekten dargestellt , sodass der Programmierer mit jedem Element
auf der HTML-Seite
arbeiten kann . Es gibt zahlreiche Befehle
für die Arbeit mit dem DOM. Ich behandle diese Themen ausführlich in meinem
Kurs Erste Schritte und habe einige dieser
Themen in den Anhang
aufgenommen. Wenn Sie überprüfen müssen. Ich habe Informationen zum
DOM und Befehle
zum Auswählen und Arbeiten
mit DOM-Elementen beigefügt . Ordnung, jetzt zurück
zum aktuellen Thema. Wenn Sie
einen Ereignis-Listener an ein
Objekt oder ein DOM-Element angehängt einen Ereignis-Listener an ein
Objekt oder ein DOM-Element angehängt und dieses Ereignis nicht
mehr verwendet wird. Es ist eine gute Praxis
, den Zuhörer zu entfernen. Schauen wir uns also ein Beispiel an. Werfen wir einen Blick auf den
HTML-Code für diese Seite
, den ich gerade zeige. Hier ist es, wie Sie sehen können, eine ziemlich einfache HTML-Seite. Wir haben einen Titel in der Überschrift, wir haben etwas CSS. Dann haben
wir im Körper hier ein paar div-Tags. Und was ich tun möchte,
ist, dass ich
hier
einen Event-Listener
an diesen div-Tag anhängen einen Event-Listener
an diesen div-Tag möchte, der eine ID des Titels hat. Wenn wir uns also
unseren JavaScript-Code ansehen, wie Sie sehen können, ist diese app.js an diese HTML-Datei
angehängt. Wir haben hier ein
paar Variablen deklariert. Jetzt mache ich
das einfach , um hier ein Beispiel zu
zeigen. Also habe ich einige
globale Variablen verwendet , weil es so einfach ist. Ich weiß nicht, ich nehme mir nicht die Zeit, es anders
zu machen. Ich möchte nur dieses Beispiel
zeigen. Wir haben hier also einige globale
Variablen. Eine ist Konto und eine
ist eine Titelvariable, die das div
speichert, das die ID title
hat. So wähle ich es dort aus. Also werden wir dem einen
Event-Listener hinzufügen. Also komme ich hier runter und nehme einfach diese Variable
dort, füge Event-Listener hinzu. Und wir müssen angeben, um
welches Ereignis es sich handelt. Es ist ein Klickereignis, das wir verwenden möchten. Und welche Funktion heißt
jetzt That's title? Klicken Sie hier auf diese Funktion. Jetzt können Sie manchmal
Ereignis-Listener mit
anonymen Funktionen hinzufügen , bei denen Sie die
Funktion genau hier deklarieren, anstatt sie zu deklarieren,
bevor Sie sie im
add-Event-Listener deklarieren. Und das ist in Ordnung. Sie müssen sich jedoch bewusst sein,
dass Sie nicht entfernen können den Ereignis-Listener in diesem Fall
den Ereignis-Listener nicht entfernen können. In diesem Fall
müssen Sie ihn möglicherweise entfernen Dann sollten Sie dies auf diese Weise tun. Ordnung. Ich werde gleich über den
Grund dafür sprechen wenn
wir an diesem Punkt angelangt sind. Aber zuerst stellen wir
sicher, dass das funktioniert.
Das werde ich mir sparen. Ich habe den virtuellen
Server bereits auf dieser Seite ausgeführt. Also werde ich einfach
die Größe ändern. Und lassen Sie uns die
Konsole zeigen, damit wir die Konsolenprotokollmeldung
sehen können , wenn ich auf den Titel klicke. Und wie wir sehen können, wird das
angezeigt und der Zähler
erhöht und zeigt so
oft an, dass er angeklickt wurde. Ordnung, so ziemlich einfach. Wir haben den
EventListener dort hinzugefügt. Schauen wir uns nun an, wie wir diesen
Event-Listener entfernen
würden. Nehmen wir an,
wir wollten es entfernen sobald die Anzahl
größer als fünf war. Also machen wir
es einfach schnell. If-Aussage. Wenn die Anzahl
größer als fünf ist. Nun, das ist eine
Situation, in der wir den Event-Listener
entfernen werden.
Und hier ist der Befehl. Wir müssen dasselbe Objekt verwenden , an das der
Ereignis-Listener angehängt ist. In diesem Fall ist es
ein DOM-Element. Also tidal dot und
dann ist der Befehl remove event,
listener, so. Jetzt muss dieser Teil in den
Klammern mit dem
übereinstimmen, was wir hier
unten hatten , als wir den EventListener
eingerichtet haben. Und deshalb sage ich , wenn Sie
anonyme Funktionen verwenden, können
Sie das nicht zum Laufen bringen. Sie müssen die
Funktion vorher deklarieren. Diese Dinge sind also die gleichen. Und selbst wenn Sie
Optionen deklarieren oder Capture verwenden , müssen
Sie sie beim
Einrichten des addEventListener ebenfalls hier einfügen, um sie zu entfernen. Das ist eine der Anforderungen dieses Befehls remove event
listener. Ordnung, also lasst uns
weitermachen und das speichern. Dadurch wird die Seite aktualisiert. Sie können sehen, dass diese
Nachrichten verschwunden sind. Wenn wir jetzt anfangen, darauf zu klicken ,
zählt, wir bekommen sechs. Jetzt sollte es entfernt werden. Jetzt klicke ich darauf
und nichts passiert. Dieser Ereignis-Listener wurde entfernt. Das ist also im Grunde der Prozess des Entfernens eines Event-Listener. Ich wollte es
hier behandeln, weil wir über
Müllabfuhr
gesprochen haben. Ordnung, lass uns weitermachen.
7. Das Verständnis der Event: Bevor wir jetzt über die
JavaScript-Engine
sprechen, müssen
wir über
die Ereignisschleife sprechen. Bis zu diesem Punkt haben
wir festgestellt, dass
JavaScript ein Single-Thread ist. Es hat nur einen Aufruf-Stack. Es kann immer nur eine
Sache gleichzeitig tun, also ist es synchron. Mit JavaScript können wir
jedoch asynchrone Codierung durchführen. Ein einfaches Beispiel dafür ist das Hinzufügen einer Schaltfläche zu einer HTML-Seite. Wir können
etwas JavaScript ausführen. Der Benutzer klickt auf die Schaltfläche und wir können
auf diesen Klick reagieren. Weil wir JavaScript
laufen lassen und etwas anderes machen. Es hindert den Benutzer
nicht daran, auf diese Schaltfläche zu klicken. Das
wäre natürlich eine schreckliche Erfahrung in
einem Browser. Ein anderes Beispiel ist,
wenn wir
versuchen , einige Daten
aus einer Datenbank abzurufen, rufen
wir
die Datenbank auf und dann können
wir etwas
anderes tun , während wir auf die Rückgabe der Daten
warten. Wir müssen nicht auf
diese Daten warten , bevor wir etwas anderes
tun. Und das würde andere
JavaScript-Verarbeitungen blockieren. Wir können etwas anderes machen. Und wenn die Daten dann zurückkehren, können
wir auf diese Daten reagieren. Wir können diese
asynchrone Codierung in
JavaScript aufgrund
der Ereignisschleife erreichen . Im vorherigen Szenario wurde
der Befehl setTimeout von der Web-API
verarbeitet. Und ich erwähnte An diesem Punkt
vergisst die JavaScript-Engine alles. Nun, sobald dieses
Timing-Ereignis abgeschlossen ist, sobald die Web-API
beim Timing-Ereignis abgeschlossen ist, wie wird es wieder in
den Aufruf-Stack
integriert , sodass
die Aufgabe, die wir erledigen möchten,
erledigt wird. Wenn Sie sich beispielsweise erinnern, haben
wir eine Callback-Funktion
als Teil von setTimeout. Wie gibt diese
Rückruffunktion an die JavaScript-Engine
zurück. Lassen Sie uns das
vorherige Szenario noch einmal durchgehen, aber dieses Mal werden wir
die Ereignisschleife einbeziehen. Noch einmal. Hier ist unser Code,
hier ist unser setTimeout. Und beachte, dass wir hier
eine Funktion haben. Die gesamte Funktion enthält
eine Konsolenprotokollanweisung, das ist alles. Die Millisekunden sind auf 0 gesetzt, daher sollte der Timer sofort
ablaufen. Aber schauen wir mal, was passiert. Wir sind an dem Punkt angelangt, an dem die
Hello-World-Funktion aufgerufen wird. Lassen Sie uns das also weiter
durchgehen. Wir haben also den Aufruf der hello-world-Funktion,
die dem Aufruf-Stack hinzugefügt
wird. Und dann beginnt
es,
die Befehle innerhalb
dieser Funktion zu bearbeiten. Der erste
Befehl, auf den wir stoßen, ist eine Konsolenprotokollanweisung,
und sie wird die Variable a in der Konsole
protokollieren. Und das wurde dem Call-Stack hinzugefügt
. Es kümmert sich um
diese Log-Anweisung. Wir sehen Hallo auf der Konsole. Und dann wird der Befehl
console log aus dem Aufruf-Stack entfernt. Und dann gehen wir
in dieser Funktion weiter, wir stoßen auf setTimeout. Jetzt
weiß die JavaScript-Engine , dass setTimeout von der Web-API
verarbeitet wird, sodass es zur Bearbeitung
dorthin gesendet wird. Die Web-API richtet also einen Timer ein. Es hat die
Fähigkeit, einen Timer auszuführen. Und dieser Timer
läuft sofort ab , weil wir nicht
auf 0 Millisekunden eingestellt haben. Und wenn der Timer abläuft, was macht er mit
dieser Callback-Funktion? Das ist die Sache, die der
Timer tun sollte. Und was es tut, ist
die Callback-Funktion zur Nachrichtenwarteschlange hinzuzufügen. Jetzt befindet sich diese
Callback-Funktion in der Nachrichtenwarteschlange und an diesem Punkt kommt die
Ereignisschleife ins Spiel. Die Event-Schleife wird
weiter durchlaufen. Es wird den
Aufruf-Stack überprüfen und prüfen, ob er leer ist. Jetzt sofort. Es arbeitet immer noch an der
Hello-World-Funktion. Es ist also nicht leer, sondern in Zyklen und sieht
weiterhin Szene aus. Wenn es leer ist. Wenn es leer ist, würde
es
das nächste in der Nachrichtenwarteschlange verfügbare Element
in
der Anruf-Stack hinzufügen das nächste in der Nachrichtenwarteschlange verfügbare Element
in . Aber im Moment ist es nicht leer, also müssen wir mit
der Hello-World-Funktion fortfahren. Was kommt als
Nächstes zur Sprache? Nun, es sind weitere
Konsolenprotokollanweisungen, die dem Aufruf-Stack hinzugefügt
werden. Und wir machen weiter und vervollständigen die Konsolenprotokollanweisung World wird auf der Konsole gedruckt. Und so
wird diese
Konsolenprotokollanweisung aus dem Aufruf-Stack entfernt. An dieser Stelle
sind wir mit
der hello-world-Funktion fertig , die ebenfalls aus
dem
Aufruf-Stack entfernt wurde. Wie ich bereits erwähnt habe,
radelt die Ereignisschleife und überprüft
den Call-Stack. Also bei Checks
and see es ist es leer. Es schnappt sich dann das nächste Element in der Nachrichtenwarteschlange und fügt
es dem Aufruf-Stack hinzu. Und so holen wir diese
anonyme Funktion, diese Callback-Funktion,
aus dem Aufruf-Stack und sie beginnt zu bearbeiten
, was diese Funktion tun muss. Das einzige, was darin enthalten ist, ist
eine Konsolenlog-Anweisung. Es trifft auf diese
Konsolenprotokollanweisung und fügt sie dem Aufrufstapel hinzu. Die
Konsolenprotokollanweisung ist abgeschlossen. Ein
Ausrufezeichen wird auf
der Konsole ausgegeben , die
aus dem Aufruf-Stack entfernt wurde. Das ist das Ende
dieser Funktion, und diese Funktion wird ebenfalls
aus dem Aufruf-Stack entfernt. Und an diesem Punkt ist
der Anrufstapel leer,
es gibt nichts mehr, was
aus der Nachrichtenwarteschlange hinzugefügt werden kann. Und so
warten wir einfach auf eine Nummer, einen weiteren JavaScript-Befehl
, der ausgeführt werden muss. Ordnung, jetzt bevor wir fertig sind, möchte ich nur
einige wichtige Punkte
aus dieser Diskussion hervorheben . Erstens
können andere Teile
der JavaScript-Umgebung bestimmte Aufgaben bewältigen. Zum Beispiel die Aufgaben
, die zum Browser gehören. Die JavaScript-Engine
muss diese nicht verarbeiten. In diesem Beispiel verwenden wir die Web-API, um
diesen setTimeout-Befehl zu verarbeiten. Aber die Callbacks, die Teil dessen sind
, was
dort behandelt wird , werden mithilfe der Ereignisschleife wieder
in
die Engine integriert . Es zieht sie aus
der Nachrichtenwarteschlange und fügt sie dem Anruf-Stack hinzu. Auf diese Weise erreichen wir asynchrones
JavaScript. Die Ereignisschleife ist entscheidend
, um dies zu erreichen. Ein weiterer wichtiger Punkt: Sobald ein Callback
zum Aufruf-Stack hinzugefügt wurde, wird
der Code
vom Aufruf-Stack
so behandelt , wie es normalerweise
der Fall wäre, wenn der JavaScript-Code nicht vom Q
gekommen wäre egal. Es wird dieses
JavaScript auf die gleiche Weise verarbeiten. Als nächstes, eine Erinnerung,
sucht die Ereignisschleife ständig nach
Elementen in der Warteschlange. Und wenn der Aufruf-Stack leer ist, wenn der Aufruf-Stack leer ist und sich etwas
in der Warteschlange befindet, wird das
nächste verfügbare Element aus der Warteschlange in
den Aufruf-Stack eingefügt. Und wie bereits erwähnt, ist der
Aufruf-Stack ein Thread, also ist er synchron. Es kann jeweils nur eine
Sache tun, aber seine Interaktion
mit der Ereignisschleife und der Web-API ermöglicht die asynchrone Codierung, die wir in JavaScript erreichen
können. Ordnung, gehen wir
zum nächsten Thema über.
8. Die Node Runtime Umgebung: Da NodeJS eine
so weit verbreitete
Implementierung von JavaScript ist , denke
ich, dass es
wichtig ist, kurz auf die Laufzeitumgebung zu schauen, insbesondere in Bezug auf
die Ereignisschleife und die Nachrichtenwarteschlange wir haben
gerade darüber gesprochen. Dieser Artikel hier behandelt einige Vor- und Nachteile der Umgebung
Node.JS. Und hier ist die URL
zu diesem Artikel. Sie können es
selbst lesen, wenn Sie möchten. Aber ich wollte mir
einen Moment Zeit nehmen und mir
das Diagramm
der Laufzeitumgebung ansehen . Wenn wir also hier ein bisschen nach unten scrollen, genau hier, der Node JS Runtime. Nun, einige dieser Dinge
werden Sie erkennen,
zum Beispiel V8, hier ist die V8-Engine und sie
verarbeitet das JavaScript. Das ist es, was es tut.
Beachten Sie die Ereigniswarteschlange, einen
anderen Namen
, aber der Nachrichtenwarteschlange Die Event-Loop ist
auch ein Teil davon. Um Dinge
in der Ereigniswarteschlange zu erledigen. Dieser Teil hier live, man könnte denken, dass ähnlich
wie die Web-API
Dinge handhaben wird , die NodeJS tun muss. Das geschieht nicht durch JavaScript, durch die Umgebung
außerhalb davon. Die V8-Engine ist also
immer noch Single Thread, hat
immer noch einen Aufruf-Stack, kann
aber andere Dinge nutzen
. Und wenn man auf einem Server läuft, gibt es eine Reihe verschiedener
Dinge, die
getan werden müssen , und das wird
hier erledigt. Jetzt wissen Sie,
dass GIS einige Befehle hat , die denen ähneln, die
wir im Browser sehen. Zum Beispiel setTimeout,
set interval, beide sind verfügbar
und NodeJS auch, sie werden nicht
von der V8-Engine verarbeitet, genauso wie sie sich
nicht in einem Browser befinden. Sie werden hier gehandhabt. Und so gibt es
einige Ähnlichkeiten. Aber weil es eine
andere Umgebung ist, weil die Laufzeit anders
ist. Es wurde auf
unterschiedliche Weise gehandhabt, aber die Konzepte
sind übertragbar. Wenn Sie möchten,
können Sie in
diesem Artikel
noch einmal mehr darüber lesen . Aber ich wollte den Punkt
der Ereignisschleife und
Ähnlichkeiten zwischen
NodeJS und der
Laufzeitumgebung, die in einem Browser behandelt wird, hervorheben. Ordnung, gehen wir
zum nächsten Thema über.
9. Übung Start: Erkundung von Call und Event: Deshalb wollte ich
als Teil dieses Abschnitts eine
kleine lustige Übung machen ,
eine Gelegenheit, den Call Stack und die Event-Loop
ein wenig zu erkunden . Jetzt, bei all meinen Kursen, habe ich immer Übungen weil
ich denke, dass es wichtig
ist Sie Dinge tatsächlich
tun, um zu lernen, dass das Erledigen von Dingen auf
eigene Faust erfolgen muss mal. Und genau hier kommen
die Übungen ins Spiel. So wie ich das mache, habe ich
ein erstes Video, in dem ich
die Übung vorstelle. Und dann versuchst du es. Und wenn Sie bereit sind, fahren
Sie mit dem nächsten Thema fort. Und wir machen diese Übung durch. Das ist in der Regel die Struktur. Manchmal machen sie die Dinge
ein bisschen anders, aber das ist im Allgemeinen
die Struktur. Lassen Sie uns also einen Blick darauf
werfen , was Sie für diese Übung
tun sollen. Ordnung, die Dateien
für die Übung und speziell die
JavaScript-Datei App.js. Ich habe hier einen Code
und lass
es mich einfach sehr schnell erklären und dann gebe
ich an, was
ich von dir erwarten soll. Genau hier
erstellen wir ein Array und wir erstellen ein Array
mit 10.000 Elementen. Die Nummer, die ich
im Konstruktor verwendet habe, der Array-Konstruktor
genau dort. Und dann verwenden wir die fill-Methode von Arrays, um
das mit Einsen zu füllen. Und so
erstellt es im Grunde ein Array mit einer Länge von 10 Tausend,
das in allen eins enthält. Das machen wir hier. Dann habe ich eine kleine
Funktion, ich nenne sie Pop it. Im Grunde ist alles, was es
tut, jedes Mal, wenn
die Funktion
von diesem Array aus aufgerufen wird,
einen Wert abzulegen jedes Mal, wenn
die Funktion
von diesem Array aus aufgerufen wird,
einen Wert . Und dann rufen wir es auf. Und beachten Sie, dass wir
hier eine Rekursion haben , weil sie
die Länge des Arrays überprüft. Wenn die Länge
immer noch größer als 0 ist,
was bedeutet, dass sich immer noch
Elemente in diesem Array befinden,
ruft es sich selbst erneut auf , was dazu führt, dass ein anderes Element
angezeigt wird. Das ist Rekursion, die wir machen. Und wie Sie sich erinnern, als
wir zuvor Rekursion gemacht
haben, können wir den Stack
überlaufen lassen. Ich möchte, dass Sie sehen,
welche Nummer
erforderlich ist , um
einen Stack-Überlauf zu verursachen. Wenn 10 Tausend
für dich arbeiten, dann großartig. Aber vielleicht nicht. spielen
Sie einfach mit dieser
Anzahl von Geboten, bisschen Spaß, nur um zu
sehen, was dazu
führen wird , dass das überläuft. Und dann der zweite
Teil der Übung, wenn der
Stapel überfüllt ist, wie können Sie das ändern? Wie können Sie veranlassen, dass dies
die Ereignisschleife verwendet , damit der
Stack nicht überläuft. Also eine interessante Idee, etwas zu
nutzen, das in
der Laufzeitumgebung verfügbar ist , damit wir den Stack nicht
überlaufen lassen, aber wir können trotzdem dieselbe Nummer
verwenden aber wir können trotzdem dieselbe Nummer
verwenden
überlief den Stapel. Also gib, probiere es aus. Offensichtlich habe ich Ihnen
dafür keine
spezifischen Befehle beigebracht , obwohl Sie einige
Beispiele gesehen haben, da wir in diesem Abschnitt verschiedene
Konzepte durchgesehen haben . Aber probieren Sie das
mit dem aus, was Sie wissen. Und wenn Sie bereit sind, fahren Sie mit dem nächsten Thema fort und
wir werden es durchgehen.
10. Übung Ende: Erkundung des Call und der Event: Ordnung,
schauen wir uns diese lustige kleine
Übung hier an. Also gerade jetzt, 10 Tausend
, so viele
sind in diesem Array. Mal sehen, ob dies einen StackOverflow
verursacht. Also werde ich weitermachen und
das servieren und sehen, was wir bekommen. Also springe
ich zur HTML-Datei und klicke
dann auf Go Live. Und dann sprang ich zur Konsole. Im Moment sehen wir
keine Fehler für StackOverflow. Das scheint also okay
zu funktionieren. ich also zu
Visual Studio Code zurückkehre, werde
ich die Größe
ein wenig
reduzieren ,
damit wir das Konsolenprotokoll
sehen können ,
während wir damit spielen. Gehen
wir also auf 10.500. Mal sehen, was dort passiert. Also werde ich die
Nummer dort ändern und sie trotzdem speichern. Okay. Gehen wir zu 11 Tausend. Ich werde es speichern. Und ich
bekomme immer noch keine Probleme. Also müssen
wir vielleicht mehr hochspringen. Lass uns noch 13 Tausend gehen. Okay, lass uns 15 Tausend gehen. Und da bekommen wir einen Überlauf. Ich weiß also nicht, wie
die genaue Zahl lautet, aber das war nicht wirklich das, was
ich hier erreichen wollte. Ich wollte dir
nur die Möglichkeit geben, mit
diesem Stack-Überlauf zu spielen und zu sehen ,
dass irgendwann ,
dass irgendwann die
Stapelgröße überschritten wird. Dann haben wir hier die Reichweite „Air
Uncaught“. Ordnung, also da ist die
Luft, nach der wir suchen. Jetzt. Wie können wir das ändern? Wir können diese
Nummer also immer noch behalten und trotzdem in der Lage sein, rekursiv
auszuführen
und all diese
Elemente aus dem Array zu entfernen. Nun, um die Ereignisschleife zu
nutzen, können
wir die Web-API verwenden, wir können setTimeout verwenden,
um diese
Funktion erneut aufzurufen. Okay? Anstatt es also sofort
rekursiv zu
nennen,
können wir setTimeout verwenden, um es aufzurufen. Und so würden wir das machen, setTimeout, und dann
übergeben wir die Funktion. Jetzt schließen wir
die Klammern an
dieser Stelle nicht ein, da sie
dadurch sofort aufgerufen werden . Wir übergeben einfach die Funktion
und dann wird sie aufgerufen sobald der Timer abgelaufen ist. Also setzen wir danach
eine
0 Millisekunden, die wir sofort aufrufen
wollen. Und hier ist unser neues Setup. Lass uns das speichern
und sehen, was hier unten passiert. Beachten Sie, dass wir nicht die Luft
bekommen. Lass uns weitermachen und
einen Blick auf das Array werfen, um zu
sehen, wie viele noch übrig sind. Wir sind auf 13.600 gesunken. So viele sind also
aufgetaucht. Da wir die Ereignisschleife
verwenden, verwenden
wir natürlich die
Web-API mit setTimeout. Um diese abzunehmen. Es dauert länger
,
sie alle zu entfernen , da dieser Timer eingerichtet werden muss
. Dann wird
etwas in eine Warteschlange gestellt. Und dann wird das Element
aus der Warteschlange in den Anrufstapel
gelegt
und dann wird es angezeigt. Und das macht es immer
wieder. Schauen wir
es uns also gegen ihn an und wir haben es auf oh reduziert, wir haben jetzt 67
Tausend oder 6700 gesunken. Es bewegt sich also durch
sie hindurch, aber es ist irgendwie nett. Sie können sehen, dass es
das tut, weil
es so viel langsamer geht. Aber beachte, dass es nicht blockiert. Ich kann Sachen hier auf
der Konsole eingeben und ich bin
nicht daran gehindert andere Sachen in JavaScript zu
machen. Das ist also der Vorteil, dass
der Event-Loop dort für uns
funktioniert. Schau noch mal rein, fast fertig. Und als ich die
Eingabetaste drücke, war es erledigt. Also ist es jetzt von diesem
Array bereinigt. Also nur eine lustige kleine Übung
, um den Call Stack zu erkunden, eine Event-Loop ein bisschen. Ordnung, gehen wir
zum nächsten Thema über.
11. Wie sich JavaScript entwickelt: Als JavaScript-Entwickler ist
es wichtig
zu verstehen, wie sich
JavaScript entwickelt und verändert. Denn das ist etwas, das in der
JavaScript-Welt definitiv
ist. Es entwickelt sich ständig weiter. Als ich vor vielen Jahren anfing,
JavaScript zu verwenden, war
es nichts wie die
Sprache, die wir heute haben. Es fühlt sich fast wie eine ganz
andere Sprache an. Wir können jetzt so viel
mehr damit machen. Um zu verstehen, wie sich
JavaScript entwickelt, müssen
wir
über zwei Dinge sprechen, ekman script und TC 39. Lassen Sie uns zunächst
über das ECMO-Skript sprechen. Jetzt. Was ist ein Drehbuch? Ich bin sicher, du hast davon gehört. Es wird
ständig herumgeschlagen, im Grunde einfach
als Spezifikation von bestimmten Sprachen
verwendet wird. Es ist von
der ACM International standardisiert, und daher stammt
der Name. Javascript ist die am weitesten verbreitete
Implementierung in meinem Skript. Deshalb ist es so eng
mit JavaScript verstrickt. Aber es gibt noch andere Sprachen, von denen
Sie wahrscheinlich gehört haben. Der Fall dieses
Ekman-Skriptstandards. Zum Beispiel Action Script, die Sprache
hinter Flash, die
auf dem
Ekman-Skriptstandard und dem J-Skript basiert auf dem
Ekman-Skriptstandard und dem J-Skript , das von Microsoft erstellt wurde. Das basiert auch auf
dieser Spezifikation. Jetzt
erschien die erste Ausgabe
des Ekman-Skriptstandards im Juni 1997, und das wurde als
Ekman-Skript eins oder ES1 bezeichnet. Und seit dieser Zeit wurde für
jede weitere Version diese Zahl erhöht. Also ES x1, x2, x3 und so weiter. Jetzt, als Acme Script
Sixth veröffentlicht wurde, begannen
sie, den Mietvertrag mit dem Jahr zu benennen. Zu dieser Zeit wurde
die Veröffentlichung technisch als Ackman-Skript
2015
bezeichnet , da in
diesem Jahr Ekman Scripts
Six veröffentlicht wurde. ES6 ist jedoch einfach hängen geblieben. Und so bezeichnen die Leute das
als ES6- oder ECMO-Skript 2015. Sie gehen
dazwischen hin und her,
weil die ES6-Releases hängen geblieben sind. Diese spezielle Version war eine riesige Veröffentlichung mit einer Reihe
von Funktionen für JavaScript. Wenn Sie zu dieser Zeit in der
JavaScript-Welt waren, werden
Sie sich daran erinnern,
wie viele Dinge zu JavaScript hinzugefügt
wurden. Viele Dinge, die
jetzt regelmäßig verwendet wurden in
dieser speziellen Version hinzugefügt. Jetzt, seit diese Version
des Standards veröffentlicht wurde, gibt es jedes Jahr eine neue
Version. Und so hatten wir
Ekman-Skript, 2016201718192020. Jedes Jahr erscheint eine neue
Version. Vieles davon ist auf die Tatsache zurückzuführen, dass
die
Veröffentlichung
von Ekman Scripts Six so riesig war. Sie wollten nicht wieder eine so große
Veröffentlichung. Und so nähern sie sich der Veröffentlichung auf eine viel
überschaubarere Weise. Wer bestimmt nun, was in jeder Version enthalten
ist? Woher kommt das alles? Nun, das hat mit TC3 Nine zu
tun. Lassen Sie uns darüber sprechen. Jetzt. Tc 39 steht für
Technisches Komitee 39. Und sie sind ein Komitee
, das JavaScript weiterentwickelt. Und seine Mitglieder sind Unternehmen
wie Browseranbieter, die ein
begründetes Interesse an JavaScript haben. Der Ausschuss tritt regelmäßig zusammen und Sie können sein Protokoll
online verfolgen, wenn Sie möchten. In diesem Sinne ist
es also transparent. Damit ein Feature zur Reife gelangt und Teil einer zukünftigen
Ekman-Skript-Standardversion wird, muss
diese Funktion
mehrere Phasen durchlaufen , und wir nennen
diese Reifephasen. Daher
verwaltet der Ausschuss TC3 dynein diese Vorschläge in
diesen Phasen, verwaltet der Ausschuss TC3 dynein diese Vorschläge in
diesen Phasen bis sie als Teil
des Standards
akzeptiert werden . Deshalb möchte ich sehr schnell über
diese Phasen sprechen. Also Stufe eins oder Stufe
0, die erste Stufe. Aber Phase 0 ist eigentlich die
Einreichungsphase. Und dies ist nur eine
Einreichung einer neuen Funktion, eines Vorschlags für ein neues Feature. Und dies muss von
einem TC 39-Mitglied
oder von jemandem kommen einem TC 39-Mitglied , der
als TC 39-Mitwirkender gilt. Und im Grunde ist es ein
Dokument, das beschreibt , was die Funktion
ist, die sie wollen. Diese Phase 0. Stufe eins ist die Vorschlagsphase. Dies ist nun ein formeller
Vorschlag für das Feature. Und das muss
einen Champion haben, als Teil dieses Ausschusses
jemanden hat, der möchte, dass diese
Funktion übernommen wird. Das ist also Stufe eins. Stufe zwei ist die Entwurfsphase. Und dies ist wirklich die
erste Version dessen, was in der Spezifikation für
diese spezielle Funktion enthalten
sein wird . Sobald etwas auf die Bühne kommt, ist
es viel wahrscheinlicher, dass es irgendwann aufgenommen wird. Jetzt ist Stufe drei
die Kandidatenphase. Zu diesem Zeitpunkt
ist der Vorschlag größtenteils abgeschlossen und benötigt Feedback von
Implementierungen und Benutzern. Und dann ist die
vierte Stufe die fertige Phase. Zu diesem Zeitpunkt ist es
bereit, in
die Spezifikation aufgenommen zu werden , und wird
höchstwahrscheinlich in
die nächste kommende Spezifikation aufgenommen . Aber das ist nicht
unbedingt eine Garantie. all diesen Phasen werden
diese Funktionen
immer noch als
Vorschläge betrachtet und sind
erst dann Funktionen , wenn sie offiziell in den Standard
aufgenommen wurden. Nun kann es wichtig sein, diese
Phasen zu kennen. Wenn Sie beispielsweise
auf eine Website wie diese gehen und auf bevorstehende Funktionen zugreifen
, können Sie mit dieser Schaltfläche Weiter herausfinden, was unterstützt
und was nicht. Beachten Sie, wie es in
die Phasen unterteilt ist , über die wir gerade gesprochen haben. Hier ist die Kandidatenphase, hier ist, was
in der nächsten
Ekman-Skriptveröffentlichung möglich ist. Und Sie können sehen, dass
einige Browser und einige Compiler diese
vorgeschlagenen Funktionen
bereits unterstützen. Sie können sehen, dass Sie hier, wenn Sie in den
Phasen Entwurf zwei nach unten gehen, feststellen, dass
immer weniger Implementierungen bereits durchgeführt wurden. Da diese Anbieter also einen Sitz im Ausschuss
haben, wissen
sie, was auf sie zukommt. Sie mögen die Verfechter
eines bestimmten
Vorschlags sein , wer weiß, aber sie beginnen mit der Umsetzung
einiger dieser Dinge, bevor sie Teil der
offiziellen Spezifikation werden. Sie können sehen, dass wir sogar bis zur Stufe 0
hinuntergehen können, dort überhaupt
nicht viel los. Wenn also Artikel oder
Websites wie diese über Vorschläge
sprechen ,
Ekman-Skriptvorschläge, sprechen
sie über
Dinge, die sich in einer dieser Phasen befinden nicht offiziell
in die Standard noch, bewegen sich
aber in
diese Richtung. Das ist also der Prozess, dem
tc threonine folgt,
um den Ackman-Skriptstandard für JavaScript zu aktualisieren. Ordnung, gehen wir
zum nächsten Thema über.