JavaScript Modules: Import and Export Explained

Introduction
Modern JavaScript development heavily relies on modules to organise code into reusable and manageable pieces. In this article, we will know why modules are essential, how to use import and export statements, what the difference between default export and named export, and the benefits of writing modular code.
Why Modules Are Needed
Imagine you are building a complex web application with multiple JS files. Without modules, you might end with situation like this:
All your functions and variables live in the global scope.
You have to include
<script>tags in the correct order manually.Naming collisions become common (two files might use the same variable name).
Code is hard to maintain, test, or reuse because everything is tangled together.
Here, jsFile2.js accidentally overwrites the user variable from jsFile1.js. This is a classic global scope pollution issue.
Modules solve these problems by giving each file its own scope and providing explicit ways to share code
ES6 Modules: The Basics
An ES6 module is just a JavaScript file. Variables, functions, or classes defined in a module are private by default. To use them elsewhere, you must export them from their home module and import them into the module where they are needed.
Exporting
There are two ways to export: named exports and default exports.
Named Exports
You can export multiple items from a module by using the export keyword. For example, in a file called math.js:
// math.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
You can also export existing items later :
// math.js
const PI = 3.14159;
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
export { PI, add, subtract}
Default Export
A module can have one default export. This is often used when a module represents a single main functionality, like a class or a primary function.
// logger.js
export default function log(message) {
console.log(message);
}
You can also export a default object or a class :
// user.js
export default class User {
constructor(name) {
this.name = name;
}
}
Importing
To use an exported item in another module, you can use import keyword.
Importing Named Exports
When you are importing a named export, you must use curly braces {} and the exact names of the exports.
// app.js
import { PI, add, subtract } from "./math.js"
console.log(add(13, 12)); // 25
console.log(subtract(11, 4)); // 7
console.log(PI); // 3.14159
You can also rename using as:
// app.js
import { add as sum, subtract as minus } from './math.js';
console.log( minus(44 , 8) ); // 36
Importing Default Exports
Default imports are written without curly braces. You can name the imported value anything you like.
// app.js
import log from './logger.js';
import User from './user.js';
Mixing Default and Named Imports
You can import both in one statement :
// mathUtils.js
export const someValue = 491981
export default functon multiply ( a, b) {
return a * b
};
// app.js
import multiply, {someValue } from "./mathUtils.js";
Default vs Named Exports – When to Use Which
Named exports are great when a module exposes several functions or values. They force the importer to use the exact name (or alias), which makes the code more self-documenting.
Default exports are ideal when a module only does one main thing, like a component, a single class, or a primary function.
Best Tip: Many style guides recommend using named exports whenever possible because they make refactoring and IDE autocompletion easier.
This diagram shows how app.js imports specific name pieces from math.js and a default export from singleUtils.js .
Benefits of Modular Code
Encapsulation
Each module has its own scope. Variables and functions are not accidentally exposed to the global scope.Reusability
Well-written modules can be reused across different projects or parts of an application.Maintainability
Code is organized by feature or responsibility. You can update one module without touching others, as long as the public interface stays the same.Dependency Management
Imports make dependencies explicit. You can see exactly which files a module relies on.Easier Testing
You can test a module in isolation by importing only what you need.
Conclusion
JavaScript modules (ES6) have revolutionised the way we structure code. By using export and import, you can write clean, maintainable, and scalable applications. Start by identifying logical boundaries in your code—group related functions into modules, export what’s needed, and import where required. Soon you’ll wonder how you ever lived without them!



