So importieren/exportieren Sie eine Klasse in Vanilla JavaScript (JS)
Lesezeit: 9 Minuten
RBT
Ich verwende Vanilla JavaScript (JS). Jetzt versuche ich, das Konzept des Imports/Exports zu nutzen Klasse Und Modul die als Teil der Veröffentlichung von ECMA-2015 (ECMA-6) kam.
Bitte sehen Sie sich das folgende Code-Snippet an:
import Rectangle from 'rectangle.js';
class MyHiFiRectangle extends Rectangle {
constructor(height, width) {
super(height,width);
this.foo= "bar";
}
}
Ich versuche, auf die oben genannten JS-Dateien in einer HTML-Seite mit dem Namen zu verweisen test.html Wie nachfolgend dargestellt:
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>Javascipt by Rasik Bihari Tiwari</title>
<script src="https://stackoverflow.com/questions/44490627/Scripts/rectangle.js"></script>
<script src="Scripts/myHiFiRectangle.js"></script>
<script type="text/javascript">
var v = new MyHiFiRectangle(2,4);
console.debug(v.foo);
</script>
</head>
<body >
</body>
</html>
Dann habe ich versucht zu laden test.html im Browser. Das Ergebnis ist bei verschiedenen Browsern unterschiedlich.
Bei Google Chrome erhalte ich folgenden Fehler:
Nicht erfasster Syntaxfehler: Unerwarteter Token-Export
Auf Mozilla Firefox bekomme ich folgenden Fehler:
SyntaxError: Exportdeklarationen dürfen nur auf der obersten Ebene eines Moduls erscheinen
SyntaxError: Importdeklarationen dürfen nur auf der obersten Ebene eines Moduls erscheinen
ReferenceError: MyHiFiRectangle ist nicht definiert[Learn More]
Ich habe versucht, die JS-Dateien neu zu ordnen, auf die in der verwiesen wird Kopf -Tag der HTML-Datei, hatte aber keine Auswirkungen.
Notiz: Um es noch einmal klarzustellen, ich verwende keine Transpiler wie Babel. Ich versuche, die native Unterstützung von Export/Import zu überprüfen Klasse Und Modul Konstrukte in Vanilla JS und wie es funktioniert.
Ich habe eine Antwort auf Ihre Frage gepostet.
– neugierig.netter
16. Januar 2019 um 22:23 Uhr
Entfernen <script src="Scripts/rectangle.js"></script> und ersetzen <script src="Scripts/myHiFiRectangle.js"></script> mit <script src="Scripts/myHiFiRectangle.js" type="module"></script>. Das behebt ein Problem. Das andere ist das myHifiRectangle.js erstellt keine globale Variable (die Sie sowieso nicht mehr verwenden sollten). Um das zu bekommen, fügen Sie hinzu window.MyHiFiRectangle = MyHiFiRectangle;am Ende von myHifiRectangle.js.
– Verbindung
16. Januar 2019 um 22:25 Uhr
neugierig.netter
Ich bin das durchgegangen und habe eine Lösung mit einer dritten js-Datei als Modul. rectangle.js wird gleich sein und myHifiRectangle.js Datei haben nur eine Änderung.
import Rectangle from './rectangle.js';
export default class MyHiFiRectangle extends Rectangle {
constructor(height, width) {
super(height,width);
this.foo= "bar";
}
}
Jetzt brauchen wir eine dritte Datei, die eine Moduldatei sein wird, sagen wir, script.js
import MyHiFiRectangle from './myHifiRectangle.js'
var v = new MyHiFiRectangle(2,4);
console.log(v.foo);
Nun, die dritte Datei, script.js sollte ein Modul sein. Mehr zu Modulen Hier. Ich habe alle drei Dateien unter modelJS Ordner.
Wenn Sie jetzt laufen, sollten Sie sehen, dass „bar“ auf der Konsolenregisterkarte des Entwicklertools gedruckt wird.
Großartig! Das war mir nicht bewusst module Attribut. Möglicherweise hatte Chrome es zum Zeitpunkt des Schreibens dieser Frage nicht implementiert. Übrigens konnte ich es mit erreichen module Attribut in meiner HTML-Datei selbst wie erwähnt meine eigene Antwort. Ich brauchte kein separates script.js Dateien zum Aufrufen meiner Module. Ich weiß es wirklich zu schätzen, dass Sie sich um meine alte Frage bemüht haben. Ich habe heute etwas Neues gelernt.
– RBT
17. Januar 2019 um 1:50 Uhr
RBT
Ich füge auch eine Antwort hinzu, nachdem ich einen Hinweis von der Antwort von curiou.netter in diesem Thread erhalten habe.
Ich werde die Fehler in der genauen Reihenfolge in den Originalcodedateien aufzeigen. Übrigens konnte ich das Problem beheben, ohne zusätzliche einzubeziehen script.js Datei:
Wenn Sie sich auf JS-Module beziehen, sollte der Skripttyp sein Modul stattdessen. Ich bezog mich auf myHiFiRectancle.js wie eine normale JS-Datei mit Quelle taggen als:
src="Scripts/myHiFiRectangle.js"
Ich habe auch importiert MyHiFiRectangle Modul. Hier ist, wie die Kopf Tag sieht jetzt in der aus test.html Datei nach Behebung dieses Fehlers:
<head>
<meta charset = "UTF-8">
<title>Javascipt by Rasik Bihari Tiwari</title>
<script type="module">
import MyHiFiRectangle from './scripts/myHiFirectangle.js';
var v = new MyHiFiRectangle(2,4);
console.debug(v.foo);
</script>
</head>
Exportvorgabe Aussage fehlte myHiFiRectangle.js Datei. Jede Klasse muss als Modul exportiert werden, wenn sie von einem anderen Ort verwendet werden soll. Die korrigiert myHiFiRectangle.js Datei sieht wie folgt aus:
import Rectangle from './rectangle.js';
export default class MyHiFiRectangle extends Rectangle {
constructor(height, width) {
super(height,width);
this.foo= "bar";
}
}
Meine Skriptdateien hatten einen weiteren Fehler beim Importieren von Modulen.
Falscher Weg:
import Rectangle from 'rectangle.js';
import MyHiFiRectangle from '/scripts/myHiFirectangle.js';
Es verursacht den folgenden Fehler, der selbsterklärend ist:
Nicht erfasster TypeError: Fehler beim Auflösen des Modulbezeichners „rectangle.js“. Relative Verweise müssen entweder mit „/“, „./“ oder „../“ beginnen.
Der richtige Weg:
import Rectangle from './rectangle.js';
import MyHiFiRectangle from './scripts/myHiFirectangle.js';
Ich hatte meine Dateierweiterung namens .mjs was den Import brach. Also beim Halten type="module" Ich habe die Dateierweiterung auf .js und es funktioniert jetzt.
– Frizzant
3. April um 11:45 Uhr
Mu.
Ich möchte Ihnen eine alternative Lösung zu dem zeigen, was @Andy Gaskell gepostet hat.
Erstens benötigen Sie babel, um sicherzustellen, dass Sie ES6 in Ihrem Browser verwenden können. Dadurch soll sichergestellt werden, dass Ihr Code weiterhin funktioniert, da einige Browser (ältere Browser wie IE) moderne Javascript-Funktionen (ES6 und höher) wie Import/Export und Klassen nicht unterstützen.
vor allen anderen oben erwähnten Javascript-Dateien.
Zweitens, wenn Sie Ihre Javascript-Klassen inline einschließen, wird der Geltungsbereich dieser Klassen global, selbst wenn sie sich in ihren eigenen physischen js-Dateien befinden.
Ich habe unten ein funktionierendes Beispiel eingefügt, ich habe es ein wenig geändert, damit es im Code-Snippet funktioniert. Sie möchten das Skript durch das Skript ersetzen, das Ihre Javascript-Datei enthält, wie Sie es in Ihrem Code getan haben.
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>Javascipt by Rasik Bihari Tiwari</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<!-- Replace them with script with src pointing to your javascript -->
<script type="text/javascript">
class Rectangle{
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class MyHiFiRectangle extends Rectangle {
constructor(height, width) {
super(height,width);
this.foo= "bar";
}
}
var v = new MyHiFiRectangle(2,4);
console.log(v.foo);
</script>
</head>
<body >
</body>
</html>
AKTUALISIERT
OK. Cool! Übrigens, wenn ich die gesamte Klassendefinition in das Skript-Tag meiner HTML-Seite selbst bringe, muss ich nicht einmal auf babel-core im Head-Tag verweisen. Warum sollte es erforderlich sein?
Sie benötigen es möglicherweise für Browser, die Klassen wie IE nicht unterstützen. Wenn die Kompatibilität mit älteren Browsern jedoch nicht zu Ihren Anforderungen gehört, benötigen Sie sie nicht.
… brauche ich überhaupt das Export-Import-Zeug? Welche Bedeutung hätte der Modulexport in einem nativen Javascript, wenn jede Klasse mehr oder weniger global ist?
In der Tat brauchen Sie das Export-Import-Zeug nicht, da Ihre Klassen global sind. Diese verwenden Sie nur, wenn Sie das Modulsystem nutzen möchten. Wenn Sie Import/Export nicht verwenden, sollten Ihre Klassen global sein und daher funktionieren. Aber für den Fall, dass es irgendwie nicht ging. Sie stellen sicher, dass es global vorhanden ist, indem Sie es wie folgt an ein Fensterobjekt anhängen:
window.myClass = class MyClass { /* Class definition */ }
OK. Cool! Übrigens, wenn ich die gesamte Klassendefinition in das Skript-Tag meiner HTML-Seite selbst bringe, muss ich nicht einmal darauf verweisen babel-core im Head-Tag. Warum sollte es erforderlich sein? class Konstrukt wird jetzt nativ in Javascript ab ECMA-6 unterstützt. ich sollte nicht einen Transpiler benötigen, wenn Sie mit nativem Javascript-Code arbeiten. Transpiler spielen so wie sie sind keine Rolle, aber sie treten in Aktion, wenn sie von einem Modul-Bundler wie Webpack oder Browserify aufgerufen werden.
– RBT
15. Juni 2017 um 0:58 Uhr
Nun bleibt die Frage, dass das alles nicht funktioniert, wenn ich meine Klassen in einzelne separate js-Dateien verschiebe. Das Ding, das im Moment zu platzen scheint, ist export Und import in einzelnen js-Dateien passiert. Aber wenn ich alle js-Dateien (die die Klassendateien enthalten) in sequenzieller/erforderlicher Weise (in der Reihenfolge, in der auf sie verwiesen wird) auf der Seite, auf der ich sie verwende, eingefügt habe, brauche ich dann überhaupt das Export-Import-Zeug? Welche Bedeutung hätte der Modulexport in einem nativen Javascript, wenn jede Klasse mehr oder weniger global ist?
– RBT
15. Juni 2017 um 1:05 Uhr
OK. Also gemäß dem Modulsystem (vorausgesetzt, wir sprechen von einem Tag, an dem aktuelle Browser das Export- / Import-Ding implementiert haben) – In dem Moment, in dem ich die Export-Anweisung für eine Klasse verwende, die sich in einer eigenen js-Datei befindet, wird sie plötzlich nicht mehr global und wird verfügbar sein für nur jene Skriptdateien, die es explizit mit dem Schlüsselwort import importieren, das in der ECMA6-Spezifikation verfügbar ist. Ist das eine faire Aussage?
– RBT
15. Juni 2017 um 3:18 Uhr
Ja. Ich glaube, das ist richtig. Sie können sehen, dass dies zutrifft, wenn Sie versuchen, eine Datei dorthin zu importieren export ... existiert nicht (in Ihrer js-App). Die Datei, die versucht, das besagte Modul zu importieren, wird sich beschweren. Das liegt am Modulsystem. Der Umfang des Codes bleibt in einer Datei erhalten, es sei denn, sie werden importiert/exportiert.
– Mu.
15. Juni 2017 um 3:24 Uhr
Können Sie Ihrer Antwort der Vollständigkeit halber bitte einen Hinweis hinzufügen, dass Schlüsselwörter zum Exportieren/Importieren derzeit nicht funktionieren, da sie sich noch in der Implementierungsphase (in Bezug auf die ECMA-6-Spezifikationen) durch verschiedene Browseranbieter befinden. Mein Code-Snippet funktioniert auch, wenn ich Export-Import-Anweisungen aus ihnen entferne, da alle Klassen standardmäßig global sind, auch wenn sie sich in ihren eigenen physischen *.js-Dateien befinden.
Ich habe eine Antwort auf Ihre Frage gepostet.
– neugierig.netter
16. Januar 2019 um 22:23 Uhr
Entfernen
<script src="Scripts/rectangle.js"></script>
und ersetzen<script src="Scripts/myHiFiRectangle.js"></script>
mit<script src="Scripts/myHiFiRectangle.js" type="module"></script>
. Das behebt ein Problem. Das andere ist dasmyHifiRectangle.js
erstellt keine globale Variable (die Sie sowieso nicht mehr verwenden sollten). Um das zu bekommen, fügen Sie hinzuwindow.MyHiFiRectangle = MyHiFiRectangle;
am Ende vonmyHifiRectangle.js
.– Verbindung
16. Januar 2019 um 22:25 Uhr