Start · Sprachen · JavaScript · Referenz · export

export

Anweisung

Die <code>export</code>-Deklaration exportiert Werte aus einem JavaScript-Modul, die anschließend per <code>import</code> in anderen Programmen verwendet werden können.

seit JavaScript ES2015 (ES6) — Baseline: alle modernen Browser, No Kategorie: syntax

Signatur

export name1, name2, /* …, */ nameN; / export { name1, /* …, */ nameN }; / export default expression; / export * from "module-name";

Beschreibung

Die export-Deklaration wird verwendet, um Werte aus einem JavaScript-Modul zu exportieren. Exportierte Werte können anschließend mit der import-Deklaration oder mit dynamischem Import in andere Programme importiert werden. Der Wert einer importierten Bindung kann sich in dem Modul, das sie exportiert, ändern — wenn ein Modul den Wert einer exportierten Bindung aktualisiert, wird die Aktualisierung auch im importierten Wert sichtbar.

Damit die export-Deklaration in einer Quelldatei verwendet werden kann, muss die Datei vom Runtime als Modul interpretiert werden. In HTML geschieht dies, indem dem <script>-Tag type="module" hinzugefügt wird oder indem es von einem anderen Modul importiert wird. Module werden automatisch im strict mode interpretiert.

Jedes Modul kann zwei verschiedene Arten von Exports haben: named export und default export. Pro Modul sind mehrere named exports möglich, aber nur ein default export. Jede Art entspricht einer der oben gezeigten Syntaxformen.

Nach dem Schlüsselwort export können let-, const- und var-Deklarationen sowie Funktions- oder Klassendeklarationen verwendet werden. Man kann auch die Syntax export { name1, name2 } nutzen, um eine Liste an anderer Stelle deklarierter Namen zu exportieren. Beachte, dass export {} kein leeres Objekt exportiert — es handelt sich um eine No-op-Deklaration, die nichts exportiert (eine leere Namensliste).

Man kann export nicht auf eine using- oder await using-Deklaration anwenden. Es ist jedoch möglich, eine an anderer Stelle mit using oder await using deklarierte Variable zu exportieren. Dies wird trotzdem dringend abgeraten, da die Variable entsorgt wird, sobald das Modul die Ausführung beendet, sodass alle Importer einen bereits entsorgten Wert erhalten.

Export-Deklarationen unterliegen nicht den Regeln der temporal dead zone. Man kann deklarieren, dass das Modul X exportiert, bevor der Name X selbst deklariert ist.

Die Syntax export default erlaubt jeden Ausdruck. Als Sonderfall werden Funktionen und Klassen als Deklarationen, nicht als Ausdrücke, exportiert, und diese Deklarationen können anonym sein. Das bedeutet, Funktionen werden gehoistet.

Named exports sind nützlich, wenn mehrere Werte exportiert werden müssen. Beim Importieren müssen named exports mit exakt demselben Namen referenziert werden (optional per as umbenannt), aber der default export kann unter jedem beliebigen Namen importiert werden.

Man kann named exports auch umbenennen, um Namenskonflikte zu vermeiden. Ein Name kann sogar in etwas umbenannt werden, das kein gültiger Identifier ist, indem ein String-Literal verwendet wird.

Re-Exporting / Aggregation

Ein Modul kann außerdem Werte, die von anderen Modulen exportiert werden, „weiterreichen", ohne dass zwei getrennte import/export-Anweisungen geschrieben werden müssen. Dies ist oft nützlich, um ein einzelnes Modul zu erstellen, das verschiedene Exports aus verschiedenen Modulen bündelt (üblicherweise „Barrel-Modul" genannt).

Dies wird mit der „export from"-Syntax erreicht. Sie ist vergleichbar mit einer Kombination aus import und export, mit dem Unterschied, dass function1 und function2 nicht innerhalb des aktuellen Moduls verfügbar werden. Die meisten „import from"-Syntaxen haben ein „export from"-Gegenstück.

Es gibt auch export * from "mod", obwohl es kein import * from "mod" gibt. Dies exportiert alle named exports von mod als named exports des aktuellen Moduls erneut, aber der default export von mod wird nicht re-exportiert. Wenn zwei Wildcard-Export-Anweisungen implizit denselben Namen re-exportieren, wird keiner von beiden re-exportiert.

Der Versuch, den doppelten Namen direkt zu importieren, löst einen Fehler aus.

Die korrekte Vorgehensweise ist, den Export umzubenennen. Die „export from"-Syntax erlaubt es, das as-Token wegzulassen, wodurch der default export weiterhin als default export re-exportiert wird.

export from unterstützt alle Features, die import unterstützt — zum Beispiel import attributes.

Parameter

Name Typ Default Beschreibung
$nameN Pflicht Identifier Identifier, der exportiert werden soll (sodass er in einem anderen Skript per import importiert werden kann). Wird mit as ein Alias verwendet, kann der tatsächlich exportierte Name als String-Literal angegeben werden, der kein gültiger Identifier sein muss.

Beispiele

Named exports verwenden — my-module.js

// module "my-module.js"
function cube(x) {
  return x * x * x;
}

const foo = Math.PI + Math.SQRT2;

const graph = {
  options: {
    color: "white",
    thickness: "2px",
  },
  draw() {
    console.log("From graph draw function");
  },
};

export { cube, foo, graph };

Named exports verwenden — Konsument

import { cube, foo, graph } from "./my-module.js";

graph.options = {
  color: "blue",
  thickness: "3px",
};

graph.draw(); // Logs "From graph draw function"
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888

Default export verwenden — cube.js

// module "cube.js"

export default function cube(x) {
  return x * x * x;
}

Default export importieren

import cube from "./cube.js";

console.log(cube(3)); // 27

export from — childModule1.js

// In childModule1.js
function myFunction() {
  console.log("Hello!");
}
const myVariable = 1;
export { myFunction, myVariable };

export from — childModule2.js

// In childModule2.js
class MyClass {
  constructor(x) {
    this.x = x;
  }
}

export { MyClass };

export from — parentModule.js

// In parentModule.js
// Only aggregating the exports from childModule1 and childModule2
// to re-export them
export { myFunction, myVariable } from "childModule1.js";
export { MyClass } from "childModule2.js";

export from — Top-Level-Modul

// In top-level module
// We can consume the exports from a single module since parentModule
// "collected"/"bundled" them in a single source
import { myFunction, myVariable, MyClass } from "parentModule.js";

Named exports

// export features declared elsewhere
export { myFunction2, myVariable2 };

// export individual features (can export var, let,
// const, function, class)
export let myVariable = Math.sqrt(2);
export function myFunction() {
  // …
}

using nicht direkt exportierbar

export using resource1 = getResource(); // SyntaxError

// Allowed by syntax but discouraged
using resource2 = getResource();
export { resource2 };

Keine TDZ bei export

export { x };
const x = 1;
// This works, because `export` is only a declaration, but doesn't
// utilize the value of `x`.

Default exports

// export feature declared elsewhere as default
export { myFunction as default };
// This is equivalent to:
export default myFunction;

// export individual features as default
export default function () { /* … */ }
export default class { /* … */ }

export default mit Ausdruck

export default 1 + 1;

Anonyme default-Deklarationen

// Works because `foo` is a function declaration,
// not a function expression
foo();

export default function foo() {
  console.log("Hi");
}

// It's still technically a declaration, but it's allowed
// to be anonymous
export default function () {
  console.log("Hi");
}

Default export mit beliebigem Namen importieren

// file test.js
const k = 12;
export default k;

Default export importieren mit anderem Namen

// some other file
import m from "./test"; // note that we have the freedom to use import m instead of import k, because k was default export

console.log(m); // 12

Named exports umbenennen

export { myFunction as function1, myVariable as variable };

Umbenennung mit String-Literal

export { myFunction as "my-function" };

Re-Export mit Umbenennung

export { default as function1, function2 } from "bar.js";

Äquivalent aus import und export

import { default as function1, function2 } from "bar.js";

export { function1, function2 };

export from Varianten

export { x } from "mod";
export { x as v } from "mod";
export * as ns from "mod";

Konflikt bei Wildcard-Re-Exports

// -- mod1.js --
export const a = 1;

// -- mod2.js --
export const a = 3;

// -- barrel.js --
export * from "./mod1.js";
export * from "./mod2.js";

// -- main.js --
import * as ns from "./barrel.js";

console.log(ns.a); // undefined

Direkter Import eines konfliktbehafteten Namens

import { a } from "./barrel.js";
// SyntaxError: The requested module './barrel.js' contains conflicting star exports for name 'a'

Ungültige Syntax

export DefaultExport from "bar.js"; // Invalid

Korrekte Umbenennung des default

export { default as DefaultExport } from "bar.js";

as-Token weglassen

export { default, function2 } from "bar.js";

Re-Export mit import attributes

export { default } from "./data.json" with { type: "json" };

// Wichtig · Fallstricke

Namen für Export-Deklarationen müssen sich voneinander unterscheiden. Exports mit doppelten Namen oder die Verwendung von mehr als einem default-Export führen zu einem SyntaxError und verhindern, dass das Modul ausgewertet wird. — Aufgrund des Fehlens der Syntax export DefaultExport from "bar.js" hat auch import source kein Re-Export-Gegenstück. Ebenso hat die import defer * as ns-Deklaration kein Re-Export-Gegenstück, obwohl import * as ns eines hat.

Siehe auch