Heim Web-Frontend js-Tutorial Implementierungsmethode zum zyklischen Laden von JavaScript-Modulen_Javascript-Fähigkeiten

Implementierungsmethode zum zyklischen Laden von JavaScript-Modulen_Javascript-Fähigkeiten

May 16, 2016 pm 03:26 PM

„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.

1

2

3

4

5

// a.js

var b = require('b');

 

// b.js

var a = require('a');

Nach dem Login kopieren

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.

1

2

3

4

5

6

{

 id: '...',

 exports: { ... },

 loaded: true,

 ...

}

Nach dem Login kopieren

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.

1

2

3

4

5

exports.done = false;

var b = require('./b.js');

console.log('在 a.js 之中,b.done = %j', b.done);

exports.done = true;

console.log('a.js 执行完毕');

Nach dem Login kopieren

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.

1

2

3

4

5

exports.done = false;

var a = require('./a.js');

console.log('在 b.js 之中,a.done = %j', a.done);

exports.done = true;

console.log('b.js 执行完毕');

Nach dem Login kopieren

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.

1

2

3

var a = require('./a.js');

var b = require('./b.js');

console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);

Nach dem Login kopieren

Führen Sie main.js aus und die Ergebnisse sind wie folgt.

1

2

3

4

5

6

7

$ 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

Nach dem Login kopieren

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.

1

2

3

4

5

6

7

8

// 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);

Nach dem Login kopieren

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.

1

2

3

4

$ babel-node m2.js

 

bar

baz

Nach dem Login kopieren

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).

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// 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();

 }

}

Nach dem Login kopieren

按照CommonJS规范,上面的代码是没法执行的。a先加载b,然后b又加载a,这时a还没有任何执行结果,所以输出结果为null,即对于b.js来说,变量foo的值等于null,后面的foo()就会报错。

但是,ES6可以执行上面的代码。

$ babel-node a.js

执行完毕

a.js之所以能够执行,原因就在于ES6加载的变量,都是动态引用其所在的模块。只要引用是存在的,代码就能执行。

我们再来看ES6模块加载器SystemJS给出的一个例子。

1

2

3

4

5

6

7

8

9

10

11

12

13

// 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);

}

Nach dem Login kopieren

上面代码中,even.js里面的函数foo有一个参数n,只要不等于0,就会减去1,传入加载的odd()。odd.js也会做类似操作。

运行上面这段代码,结果如下。

1

2

3

4

5

6

7

8

9

10

$ babel-node

> import * as m from './even.js';

> m.even(10);

true

> m.counter

6

> m.even(20)

true

> m.counter

17

Nach dem Login kopieren

上面代码中,参数n从10变为0的过程中,foo()一共会执行6次,所以变量counter等于6。第二次调用even()时,参数n从20变为0,foo()一共会执行11次,加上前面的6次,所以变量counter等于17。

这个例子要是改写成CommonJS,就根本无法执行,会报错。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// 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);

}

Nach dem Login kopieren

上面代码中,even.js加载odd.js,而odd.js又去加载even.js,形成"循环加载"。这时,执行引擎就会输出even.js已经执行的部分(不存在任何结果),所以在odd.js之中,变量even等于null,等到后面调用even(n-1)就会报错。

1

2

3

4

$ node

> var m = require('./even');

> m.even(10)

TypeError: even is not a function

Nach dem Login kopieren

[说明] 本文是我写的《ECMAScript 6入门》第20章《Module》中的一节。

Erklärung dieser Website
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

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was soll ich tun, wenn ich auf den Codendruck auf Kleidungsstücke für Front-End-Thermalpapier-Quittungen stoße? Was soll ich tun, wenn ich auf den Codendruck auf Kleidungsstücke für Front-End-Thermalpapier-Quittungen stoße? Apr 04, 2025 pm 02:42 PM

Häufig gestellte Fragen und Lösungen für das Ticket-Ticket-Ticket-Ticket in Front-End im Front-End-Entwicklungsdruck ist der Ticketdruck eine häufige Voraussetzung. Viele Entwickler implementieren jedoch ...

Entmystifizieren JavaScript: Was es tut und warum es wichtig ist Entmystifizieren JavaScript: Was es tut und warum es wichtig ist Apr 09, 2025 am 12:07 AM

JavaScript ist der Eckpfeiler der modernen Webentwicklung. Zu den Hauptfunktionen gehören eine ereignisorientierte Programmierung, die Erzeugung der dynamischen Inhalte und die asynchrone Programmierung. 1) Ereignisgesteuerte Programmierung ermöglicht es Webseiten, sich dynamisch entsprechend den Benutzeroperationen zu ändern. 2) Die dynamische Inhaltsgenerierung ermöglicht die Anpassung der Seiteninhalte gemäß den Bedingungen. 3) Asynchrone Programmierung stellt sicher, dass die Benutzeroberfläche nicht blockiert ist. JavaScript wird häufig in der Webinteraktion, der einseitigen Anwendung und der serverseitigen Entwicklung verwendet, wodurch die Flexibilität der Benutzererfahrung und die plattformübergreifende Entwicklung erheblich verbessert wird.

Wer bekommt mehr Python oder JavaScript bezahlt? Wer bekommt mehr Python oder JavaScript bezahlt? Apr 04, 2025 am 12:09 AM

Es gibt kein absolutes Gehalt für Python- und JavaScript -Entwickler, je nach Fähigkeiten und Branchenbedürfnissen. 1. Python kann mehr in Datenwissenschaft und maschinellem Lernen bezahlt werden. 2. JavaScript hat eine große Nachfrage in der Entwicklung von Front-End- und Full-Stack-Entwicklung, und sein Gehalt ist auch beträchtlich. 3. Einflussfaktoren umfassen Erfahrung, geografische Standort, Unternehmensgröße und spezifische Fähigkeiten.

Wie fusioniere ich Arrayelemente mit derselben ID mit JavaScript in ein Objekt? Wie fusioniere ich Arrayelemente mit derselben ID mit JavaScript in ein Objekt? Apr 04, 2025 pm 05:09 PM

Wie fusioniere ich Array -Elemente mit derselben ID in ein Objekt in JavaScript? Bei der Verarbeitung von Daten begegnen wir häufig die Notwendigkeit, dieselbe ID zu haben ...

Ist JavaScript schwer zu lernen? Ist JavaScript schwer zu lernen? Apr 03, 2025 am 12:20 AM

JavaScript zu lernen ist nicht schwierig, aber es ist schwierig. 1) Verstehen Sie grundlegende Konzepte wie Variablen, Datentypen, Funktionen usw. 2) Beherrschen Sie die asynchrone Programmierung und implementieren Sie sie durch Ereignisschleifen. 3) Verwenden Sie DOM -Operationen und versprechen Sie, asynchrone Anfragen zu bearbeiten. 4) Vermeiden Sie häufige Fehler und verwenden Sie Debugging -Techniken. 5) Die Leistung optimieren und Best Practices befolgen.

Wie kann man Parallax -Scrolling- und Element -Animationseffekte wie die offizielle Website von Shiseido erzielen?
oder:
Wie können wir den Animationseffekt erzielen, der von der Seite mit der Seite mit der offiziellen Website von Shiseido begleitet wird? Wie kann man Parallax -Scrolling- und Element -Animationseffekte wie die offizielle Website von Shiseido erzielen? oder: Wie können wir den Animationseffekt erzielen, der von der Seite mit der Seite mit der offiziellen Website von Shiseido begleitet wird? Apr 04, 2025 pm 05:36 PM

Diskussion über die Realisierung von Parallaxe -Scrolling- und Elementanimationseffekten in diesem Artikel wird untersuchen, wie die offizielle Website der Shiseeido -Website (https://www.shiseeido.co.jp/sb/wonderland/) ähnlich ist ...

Der Unterschied in der Konsole.log -Ausgabeergebnis: Warum unterscheiden sich die beiden Anrufe? Der Unterschied in der Konsole.log -Ausgabeergebnis: Warum unterscheiden sich die beiden Anrufe? Apr 04, 2025 pm 05:12 PM

Eingehende Diskussion der Ursachen des Unterschieds in der Konsole.log-Ausgabe. In diesem Artikel wird die Unterschiede in den Ausgabeergebnissen der Konsolenfunktion in einem Code analysiert und die Gründe dafür erläutert. � ...

So implementieren Sie die Funktion des Ziell- und Drop-Einstellungsfunktion, ähnlich wie bei VSCODE in der Front-End-Entwicklung? So implementieren Sie die Funktion des Ziell- und Drop-Einstellungsfunktion, ähnlich wie bei VSCODE in der Front-End-Entwicklung? Apr 04, 2025 pm 02:06 PM

Erforschen Sie die Implementierung der Funktion des Bedien- und Drop-Einstellungsfunktion der Panel ähnlich wie VSCODE im Front-End. In der Front-End-Entwicklung wird VSCODE ähnlich wie VSCODE implementiert ...

See all articles