Javascript Module: Import und Export

Javascript Import und Export

ES6 Module werden mittels des import-Schlüsselworts in ein Script oder inline mit <script type="module"> geladen. Javascript nutzt das Schlüsselwort import, um Funktionen und Objekte einzulesen, die aus einem anderen Modul exportiert wurden.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

Module importieren und Exportieren

Scripte und Programme sind einfacher in den Griff zu kriegen, wenn sie klein und überschaubar bleiben. Diese Binsenweisheit steckte schon in den frühen Tagen der Programmiersprachen hinter der Idee von Funktionen.

Wer von PHP kommt oder mit Server Side Includes vertraut ist, kennt bereits Mechanismen wie require und include, in Node.js haben wir ebenfalls ein require ().

PHP require('somefile.php');

SSI <!--#include virtual="/inc/base.inc" -->

Node.js const svglist = require ("./headSvgUrls");

Wir scollen rauf und runter im Script, suchen einen Variablennamen, rufen uns Objekte und Funktionen zurück ins Gedächtnis, und am nächsten Tag geht die Übersicht völlig in die Binsen. Javascript-Module beheben dieses Dilemma, indem sie das Script in kleinere Teile herunterbrechen und in separaten Dateien speichern. Dann werden die Module in das Original-Script zurückgeholt: Sie werden importiert.

Das type-Attribut des script-Elements kennzeichnet JavaScript-Dateien als module. Sowohl Skript-Dateien, die Module importieren, als auch Skripte, die Elemente exportieren, müssen als type="module" notiert werden.

<script src="app.js" type="module" defer></script>

Funktionen als Module exportieren / importieren

Funktionen, deren Code in der Anwendung nur stören würden, gehen in die Skript-Datei tools.js.

tools.js
const item = "GLOBAL SCOPE";

function isPlz (str) {
	return !(str.match(/^[D -]{0,2}[0-9]{5}$/)) ? false : true; 
}

function sum (a, b) {
	return `Summe von ${a} und ${b} ist ${a + b}`;
}

export {
	sum,
	isPlz
};

export { sum, isPlz } am Ende des Moduls exportiert die Funktionen des Moduls als Objekt in geschweiften Klammern. Würde nur eine Funktion exportiert, wäre die Export-Anweisung export default isPlz.

Das zentrale Skript, z.B. app.js, importiert die Funktionen des Moduls, die gebraucht werden.

app.js
import {sum, isPlz} from "./modules/tools.js";

console.log ("sum", sum(17,43));
console.log ("isPlz", isPlz ("D 20030"));

sum – "Summe von 17 und 43 ist 60" (app.js, line 18)
isPlz – true (app.js, line 19)

Das script-Tag muss neben dem src-Attribut auch type="module" aufführen.

<script src="./app.js" type="module" defer></script>

Ohne type="module" gibt es ansonsten eine Fehlermeldung "expects exactly one argument" (Safari) oder Uncaught SyntaxError: Cannot use import statement outside a module (Chrome).

Block-Scope

Eine Variable item im globalen Scope bleibt beim Import eines Moduls im Gültigkeitsbereich (Scope) des Moduls und ist nur innerhalb des Moduls verfügbar, in dem sie deklariert wurde.

console.log ("item", item);

ReferenceError: Can't find variable: item 
Modulcode (app.js:19)

Module sind also ein wirksamer Schutz für ihre globalen Variablen. Auf der anderen Seite gibt es keinen Zugriff auf die Funktionen, Objekte und Javascript-Klassen aus Modulen aus Inline-Skripten heraus.

Javascript class: Klassen als Modul importieren

JavaScript-Klassen werden auf dieselbe Weise exportiert wie Funktionen, z.B. in eine Datei Cupcake.js.

class Cake {
   constructor (flavor, time, deco, eggs) {
      this.flavor = flavor;
      this.time = time;
      this.deco = deco;
      this.eggs = eggs;
   }
   
   cakeRecipe() {
      return `Dieser Cupcake ist wird mit ${this.flavor} und 
              ${this.eggs} Eiern zubereitet, 
              ${this.time} min gebacken und 
              mit ${this.deco} serviert.`;
   }
}

export default Cake;

Das Beispiel exportiert nur eine Klasse, darum Export als default anstelle der Auflistung als Objekt. Die Import-Anweisung sieht nicht anders aus als beim Import der Funktionen.

Mit JavaScript-Klassen entwickeln sich Module zu sauberen Kuchenfabriken: Neue Elemente können direkt instanziert werden, ohne den Code von app.js mit den Interna der Klasse zu belasten.

import Cake from "./modules/Cupcake.js";

const c1 = new Cake ("Mohn", 15, "Mohnsahne", 0, "Marzipan" );
const c2 = new Cake ("Kirschsahne", 12, "Amarena-Kirschen", 2, "Sahne" );
console.log ("cakeRecipe" , c1.cakeRecipe ());
console.log ("cakeRecipe" , c2.cakeRecipe ());

cakeRecipe – 
Cupcake ist wird mit Mohn und 
              0 Eiern zubereitet, 
              15 min gebacken und 
              mit Mohnsahne serviert." (app.js, line 13)
cakeRecipe – 
"Dieser Cupcake ist wird mit Kirschsahne und 
              2 Eiern zubereitet, 
              12 min gebacken und 
              mit Amarena-Kirschen serviert." (app.js, line 14)

Javascript object – Objekt als Modul importieren

Exportieren und Importieren von Objekten als Module funktioniert zwar auf dieselbe Weise wie bei einer JavaScript class, aber ohne Konstruktor-Funktion bleiben Objekte Unikate.

object.js
const bookshelf = {
	title: "Alice im Wunderland",
	page: 200,
	author: "Lewis Carol",
	img: "pfad zum Bild",
	
	testChapter: function () {
    	console.log (`Das Buch ${this.title} von ${this.author} hat ${this.page} Seiten`)
  	}
}

export default bookshelf;
app.js
import book from "./modules/object.js";

book.testChapter ();
console.log ("Pfad zum Bild", book.img);

Import Syntax

Der Parameter name ist der Name des Modul-Objekts und wird zu einer Art Namensraum für Exporte. Der export-Parameter definiert individuelle Exporte, import * as name importiert alle Objekte.

Importiert wird vom relativen Pfad zur Javascript-Datei

import defaultExport from './module.js';
import * as name from './module.js';
import {square} from './module.js';
let content = import('./module.js');

./ : Dot (.) verweist auf dasselbe Verzeichnis und der Schrägstrich oder Slash gewährt den Zugriff auf das Verzeichnis.

export const add = (x, y) => {
    return x + y
}

export const subtract = (x, y) => {
    return x - y;
}
import { add, subtract } from './data';

console.log(add(2, 3));

script.js – der Vorläufer der Module

Im Grunde genommen sind Scripte, die mit dem script-Element eingebunden werden, Module, die in den globalen Scrope geladen werden. Allerdings sind ihre globalen Variablen ungeschützt. Vorsichtige Entwickler packen ihre Scripte darum in IIFE – selbstausführende Funktionen.

Javascript Module importieren u.U. selber wieder Module, die sie brauchen. Das erspart das manuelle Laden von Scripten, von denen wiederum das Modul abhängig ist.

Darüber hinaus gibt es einen dynamischen import(), der Funktionen ähnelt, aber keine Scripte mit type="module" erfordert.

Ein dynamischer Import ist sinnvoll, wenn Module unter bestimmten Bedingungen geladen werden sollen. Die statische Form wird bei Abhängigkeiten für das initiale Laden vorgezogen.