


Implementierungsmethode zum zyklischen Laden von JavaScript-Modulen_Javascript-Fähigkeiten
„Zirkuläre Abhängigkeit“ bedeutet, dass die Ausführung von Skript a von Skript b abhängt und die Ausführung von Skript b von Skript a abhängt.
// a.js var b = require('b'); // b.js var a = require('a');
Normalerweise weist „Schleifenladen“ auf das Vorhandensein einer starken Kopplung hin. Wenn es nicht richtig gehandhabt wird, kann es auch zu rekursivem Laden führen, wodurch das Programm nicht ausgeführt werden kann. Daher sollte es vermieden werden.
Tatsächlich ist dies jedoch schwer zu vermeiden, insbesondere bei großen Projekten mit komplexen Abhängigkeiten. Es ist leicht, dass a von b, b bis c und c von a abhängt. Dies bedeutet, dass der Modullademechanismus „Loop-Loading“-Situationen berücksichtigen muss.
In diesem Artikel wird erläutert, wie die JavaScript-Sprache mit dem „Schleifenladen“ umgeht. Derzeit verfügen die beiden gängigsten Modulformate CommonJS und ES6 über unterschiedliche Verarbeitungsmethoden und liefern unterschiedliche Ergebnisse.
1. Ladeprinzip des CommonJS-Moduls
Bevor wir vorstellen, wie ES6 das „Schleifenladen“ handhabt, stellen wir zunächst das Ladeprinzip des beliebtesten CommonJS-Modulformats vor.
Ein Modul von CommonJS ist eine Skriptdatei. Wenn der Befehl require das Skript zum ersten Mal lädt, führt er das gesamte Skript aus und generiert dann ein Objekt im Speicher.
{ id: '...', exports: { ... }, loaded: true, ... }
Im obigen Code ist das id-Attribut des Objekts der Modulname, das exports-Attribut ist jede vom Modul ausgegebene Schnittstelle und das geladene Attribut ist ein boolescher Wert, der angibt, ob das Skript des Moduls ausgeführt wurde. Es gibt viele weitere Attribute, die hier jedoch weggelassen werden. (Eine ausführliche Einführung finden Sie unter „require() Quellcode-Interpretation“.)
Wenn Sie dieses Modul in Zukunft verwenden müssen, erhalten Sie den Wert aus dem Exportattribut. Selbst wenn der Befehl require erneut ausgeführt wird, wird das Modul nicht erneut ausgeführt, sondern der Wert wird aus dem Cache abgerufen.
2. Schleifenladen des CommonJS-Moduls
Eine wichtige Funktion des CommonJS-Moduls ist die Ausführung beim Laden, d. h. der gesamte Skriptcode wird bei Bedarf ausgeführt. Der Ansatz von CommonJS besteht darin, dass, sobald ein Modul „in einer Schleife geladen“ ist, nur der ausgeführte Teil ausgegeben wird und der nicht ausgeführte Teil nicht ausgegeben wird.
Werfen wir einen Blick auf die Beispiele in der offiziellen Dokumentation. Der Code der Skriptdatei a.js lautet wie folgt.
exports.done = false; var b = require('./b.js'); console.log('在 a.js 之中,b.done = %j', b.done); exports.done = true; console.log('a.js 执行完毕');
Im obigen Code gibt das a.js-Skript zuerst eine fertige Variable aus und lädt dann eine andere Skriptdatei b.js. Beachten Sie, dass der a.js-Code zu diesem Zeitpunkt hier stoppt und darauf wartet, dass b.js die Ausführung abschließt, und dann die Ausführung fortsetzt.
Sehen Sie sich den b.js-Code noch einmal an.
exports.done = false; var a = require('./a.js'); console.log('在 b.js 之中,a.done = %j', a.done); exports.done = true; console.log('b.js 执行完毕');
Wenn im obigen Code b.js bis zur zweiten Zeile ausgeführt wird, wird a.js geladen. Zu diesem Zeitpunkt erfolgt das „Schleifenladen“. Das System erhält den Wert des Exportattributs des Objekts, das dem a.js-Modul entspricht. Da a.js jedoch noch nicht ausgeführt wurde, kann nur der ausgeführte Teil vom Exportattribut abgerufen werden, nicht der endgültige Wert.
Der ausgeführte Teil von a.js hat nur eine Zeile.
exports.done = false;
Daher wird für b.js nur eine Variable eingegeben, die aus a.js stammt, und der Wert ist falsch.
Dann wird b.js weiter ausgeführt. Wenn alle Ausführungen abgeschlossen sind, wird das Ausführungsrecht an a.js zurückgegeben. Daher wird a.js so lange ausgeführt, bis die Ausführung abgeschlossen ist. Wir schreiben ein Skript main.js, um diesen Prozess zu überprüfen.
var a = require('./a.js'); var b = require('./b.js'); console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);
Führen Sie main.js aus und die Ergebnisse sind wie folgt.
$ node main.js 在 b.js 之中,a.done = false b.js 执行完毕 在 a.js 之中,b.done = true a.js 执行完毕 在 main.js 之中, a.done=true, b.done=true
Der obige Code beweist zwei Dinge. Erstens wurde in b.js nicht a.js ausgeführt, sondern nur die erste Zeile. Zweitens: Wenn main.js bis zur zweiten Zeile ausgeführt wird, wird b.js nicht erneut ausgeführt, sondern das zwischengespeicherte Ausführungsergebnis von b.js wird ausgegeben, dh die vierte Zeile.
exports.done = true;
3. Schleifenladen von ES6-Modulen
Der Betriebsmechanismus von ES6-Modulen unterscheidet sich von CommonJS. Wenn der Modulladebefehl importiert wird, wird das Modul nicht ausgeführt, sondern nur eine Referenz generiert. Warten Sie, bis Sie es wirklich benötigen, und rufen Sie dann den Wert im Modul ab.
Daher sind ES6-Module dynamische Referenzen, es gibt kein Problem beim Zwischenspeichern von Werten und die Variablen im Modul sind an das Modul gebunden, in dem sie sich befinden. Bitte sehen Sie sich das Beispiel unten an.
// m1.js export var foo = 'bar'; setTimeout(() => foo = 'baz', 500); // m2.js import {foo} from './m1.js'; console.log(foo); setTimeout(() => console.log(foo), 500);
Im obigen Code ist die Variable foo von m1.js gleich bar, wenn sie zum ersten Mal geladen wird. Nach 500 Millisekunden wird sie wieder gleich baz.
Mal sehen, ob m2.js diese Änderung richtig lesen kann.
$ babel-node m2.js bar baz
Der obige Code zeigt, dass das ES6-Modul die laufenden Ergebnisse nicht zwischenspeichert, sondern dynamisch den Wert des geladenen Moduls erhält und die Variable immer an das Modul gebunden ist, in dem sie sich befindet.
Dies führt dazu, dass ES6 das „Schleifenladen“ wesentlich anders handhabt als CommonJS. ES6 kümmert sich überhaupt nicht darum, ob ein „Schleifenladen“ auftritt, es generiert lediglich einen Verweis auf das geladene Modul. Der Entwickler muss sicherstellen, dass der Wert abgerufen werden kann, wenn der Wert tatsächlich abgerufen wird.
Bitte sehen Sie sich das folgende Beispiel an (Auszug aus „Exploring ES6“ von Dr. Axel Rauschmayer).
// a.js import {bar} from './b.js'; export function foo() { bar(); console.log('执行完毕'); } foo(); // b.js import {foo} from './a.js'; export function bar() { if (Math.random() > 0.5) { foo(); } }
按照CommonJS规范,上面的代码是没法执行的。a先加载b,然后b又加载a,这时a还没有任何执行结果,所以输出结果为null,即对于b.js来说,变量foo的值等于null,后面的foo()就会报错。
但是,ES6可以执行上面的代码。
$ babel-node a.js
执行完毕
a.js之所以能够执行,原因就在于ES6加载的变量,都是动态引用其所在的模块。只要引用是存在的,代码就能执行。
我们再来看ES6模块加载器SystemJS给出的一个例子。
// even.js import { odd } from './odd' export var counter = 0; export function even(n) { counter++; return n == 0 || odd(n - 1); } // odd.js import { even } from './even'; export function odd(n) { return n != 0 && even(n - 1); }
上面代码中,even.js里面的函数foo有一个参数n,只要不等于0,就会减去1,传入加载的odd()。odd.js也会做类似操作。
运行上面这段代码,结果如下。
$ babel-node > import * as m from './even.js'; > m.even(10); true > m.counter 6 > m.even(20) true > m.counter 17
上面代码中,参数n从10变为0的过程中,foo()一共会执行6次,所以变量counter等于6。第二次调用even()时,参数n从20变为0,foo()一共会执行11次,加上前面的6次,所以变量counter等于17。
这个例子要是改写成CommonJS,就根本无法执行,会报错。
// even.js var odd = require('./odd'); var counter = 0; exports.counter = counter; exports.even = function(n) { counter++; return n == 0 || odd(n - 1); } // odd.js var even = require('./even').even; module.exports = function(n) { return n != 0 && even(n - 1); }
上面代码中,even.js加载odd.js,而odd.js又去加载even.js,形成"循环加载"。这时,执行引擎就会输出even.js已经执行的部分(不存在任何结果),所以在odd.js之中,变量even等于null,等到后面调用even(n-1)就会报错。
$ node > var m = require('./even'); > m.even(10) TypeError: even is not a function
[说明] 本文是我写的《ECMAScript 6入门》第20章《Module》中的一节。

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

Unterschiedliche JavaScript -Motoren haben unterschiedliche Auswirkungen beim Analysieren und Ausführen von JavaScript -Code, da sich die Implementierungsprinzipien und Optimierungsstrategien jeder Engine unterscheiden. 1. Lexikalanalyse: Quellcode in die lexikalische Einheit umwandeln. 2. Grammatikanalyse: Erzeugen Sie einen abstrakten Syntaxbaum. 3. Optimierung und Kompilierung: Generieren Sie den Maschinencode über den JIT -Compiler. 4. Führen Sie aus: Führen Sie den Maschinencode aus. V8 Engine optimiert durch sofortige Kompilierung und versteckte Klasse.

Zu den Anwendungen von JavaScript in der realen Welt gehören die serverseitige Programmierung, die Entwicklung mobiler Anwendungen und das Internet der Dinge. Die serverseitige Programmierung wird über node.js realisiert, die für die hohe gleichzeitige Anfrageverarbeitung geeignet sind. 2. Die Entwicklung der mobilen Anwendungen erfolgt durch reaktnative und unterstützt die plattformübergreifende Bereitstellung. 3.. Wird für die Steuerung von IoT-Geräten über die Johnny-Five-Bibliothek verwendet, geeignet für Hardware-Interaktion.

Ich habe eine funktionale SaaS-Anwendung mit mehreren Mandanten (eine EdTech-App) mit Ihrem täglichen Tech-Tool erstellt und Sie können dasselbe tun. Was ist eine SaaS-Anwendung mit mehreren Mietern? Mit Multi-Tenant-SaaS-Anwendungen können Sie mehrere Kunden aus einem Sing bedienen


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

ZendStudio 13.5.1 Mac
Leistungsstarke integrierte PHP-Entwicklungsumgebung

VSCode Windows 64-Bit-Download
Ein kostenloser und leistungsstarker IDE-Editor von Microsoft

MantisBT
Mantis ist ein einfach zu implementierendes webbasiertes Tool zur Fehlerverfolgung, das die Fehlerverfolgung von Produkten unterstützen soll. Es erfordert PHP, MySQL und einen Webserver. Schauen Sie sich unsere Demo- und Hosting-Services an.

SecLists
SecLists ist der ultimative Begleiter für Sicherheitstester. Dabei handelt es sich um eine Sammlung verschiedener Arten von Listen, die häufig bei Sicherheitsbewertungen verwendet werden, an einem Ort. SecLists trägt dazu bei, Sicherheitstests effizienter und produktiver zu gestalten, indem es bequem alle Listen bereitstellt, die ein Sicherheitstester benötigen könnte. Zu den Listentypen gehören Benutzernamen, Passwörter, URLs, Fuzzing-Payloads, Muster für vertrauliche Daten, Web-Shells und mehr. Der Tester kann dieses Repository einfach auf einen neuen Testcomputer übertragen und hat dann Zugriff auf alle Arten von Listen, die er benötigt.