JavaScript really stepped into the import and export business with ES Modules.
With ES6, the language introduced the import
and export
keywords allowing easier modularization and organization of code.
The import
keyword supports a number of different syntaxes and is often confusing when first thinking about modules.
Hopefully this article can be a concise explanation of each, and to that end we’ll start with a basic module that exports some things we can use.
const name = "Marley";
class Animal {
numberOfLegs;
name;
constructor(name, numberOfLegs) {
this.name = name;
this.numberOfLegs = numberOfLegs;
}
}
function favoriteAnimal() {
return new Animal("Dog", 4);
}
export { name as default, Animal, favoriteAnimal };
Here we have a module that exports three items: a string, a class and a function.
Notably, the name is just a string but it’s the module’s default export.
Let’s look at the different ways we can import and use the members from this module.
Importing the default export
We can import as much or as little as we need to use from our module. The simplest import brings in the default export: name.
import name from "./module";
// name === "Marley"
‘Name’ is obviously very broad so we can actually rename this import for use in our module.
import dogsName from "./module";
Now, ‘name’, the default export, has been imported with an alias. We can refer to this variable in our importing module using ‘dogsName’;
Import everything and give it a name
We can import everything from our module and we can give everything that comes in a name that we can use to access what was imported.
import * as animalStuff from "./module";
// animalStuff.name === "Marley";
// animalStuff.favoriteAnimal() =
// Animal { name: "Dog", numberOfLegs: 4 }
Importing one or more exports by name
In addition to importing the default export or everything, we can specify the names of the exports we’d like explicitly:
import { Animal, favoriteAnimal } from "./module";
This is the first time we’ve seen the curly brackets. These denote that we’re asking for specific members.
Importing specific exports and giving them an alias
In this example we can import named exports but alias them so we can use a different name in our importing module.
import { Animal as Pet, favoriteAnimal } from "./module";
const dog = new Pet(...);
Importing a module to run side-effects
This is a strange use case in that nothing is actually imported. However, any global code you might have in your module is executed.
Suppose for example, you had an additional file that contained the following code in extend.js
, responsible for adding a run method to our Animal
class:
import { Animal } from "./module";
Animal.prototype.run = function() {
console.log(`${this.name} is running!`);
};
Nothing is actually exported here, but if we wanted to use the run method in our importing module, we’d need the side-effects import:
import { Animal as Pet } from "./module";
import "./extend";
const dog = new Pet("Marley", 4);
dog.run();
import is a Promise: Dynamic Imports
Using import as a function returns a promise; these use cases are known as Dynamic Imports.
It allows you to conditionally import a module at run-time:
if (weNeedToRun === true) {
await import("./extend");
}
Hopefully this brief primer into the import
syntax has been useful. Check out the official Mozilla docs for import and export for more examples.
Top comments (0)