# 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.
    

![](https://cdn.hashnode.com/uploads/covers/696f9f5589255b82f81f6b17/3369fde4-e67d-4903-a089-867a676454ec.png align="center")

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`:

```javascript
// 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 :

```javascript
// 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.

```javascript
// logger.js
 export default function log(message) { 
    console.log(message); 
}
```

You can also export a default object or a class :

```javascript
// 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.

```javascript
// 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`:

```javascript
// 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.

```javascript
// app.js

import log from './logger.js';
import User from './user.js';


```

#### **Mixing Default and Named Imports**

You can import both in one statement :

```javascript
// 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.  
  

![](https://cdn.hashnode.com/uploads/covers/696f9f5589255b82f81f6b17/1dbe90f0-9952-4b7f-aea4-71d4e12faf95.png align="center")

This diagram shows how `app.js` imports specific name pieces from `math.js` and a default export from `singleUtils.js` .

## **Benefits of Modular Code**

1.  **Encapsulation**  
    Each module has its own scope. Variables and functions are not accidentally exposed to the global scope.
    
2.  **Reusability**  
    Well-written modules can be reused across different projects or parts of an application.
    
3.  **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.
    
4.  **Dependency Management**  
    Imports make dependencies explicit. You can see exactly which files a module relies on.
    
5.  **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!
