DEV Community

Cover image for JavaScript's Import/Export Business
Adam Barker
Adam Barker

Posted on

JavaScript's Import/Export Business

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 };
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

‘Name’ is obviously very broad so we can actually rename this import for use in our module.

import dogsName from "./module";
Enter fullscreen mode Exit fullscreen mode

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 }
Enter fullscreen mode Exit fullscreen mode

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";
Enter fullscreen mode Exit fullscreen mode

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(...);
Enter fullscreen mode Exit fullscreen mode

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!`);
};
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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");
}
Enter fullscreen mode Exit fullscreen mode

Hopefully this brief primer into the import syntax has been useful. Check out the official Mozilla docs for import and export for more examples.

Latest comments (0)