What are JavaScript modules?

JavaScript

The short answer

Modules are a way to split your code into separate files, where each file has its own scope. You can choose what to export from a module and what to import into another. This keeps your code organized, prevents naming conflicts, and makes it easier to maintain.

The problem modules solve

Before modules, all JavaScript files shared the global scope. If two files defined a variable with the same name, they would conflict:

<!-- Without modules -->
<script src="file1.js"></script>
<!-- var name = "John" -->
<script src="file2.js"></script>
<!-- var name = "Jane" — overwrites! -->

Every variable, function, and class was globally accessible. This caused naming conflicts, made it hard to track dependencies, and led to messy, tangled code.

Modules fix this by giving each file its own scope. Nothing leaks out unless you explicitly export it.

How modules work

Exporting — choosing what to share:

// utils.js
export function formatDate(date) {
return date.toLocaleDateString();
}
export function formatCurrency(amount) {
return `$${amount.toFixed(2)}`;
}
// not exported — private to this file
function helperFunction() {
// only used inside utils.js
}

Importing — using what another module shares:

// app.js
import { formatDate, formatCurrency } from './utils.js';
console.log(formatDate(new Date())); // "4/5/2026"
console.log(formatCurrency(9.5)); // "$9.50"

You can only access formatDate and formatCurrency because those are the only things that were exported. helperFunction stays private.

Named exports vs default exports

Named exports — you can have many per file:

// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
// Importing
import { add, subtract } from './math.js';

Default exports — only one per file, usually the main thing the module provides:

// Button.js
export default function Button({ children }) {
return <button>{children}</button>;
}
// Importing — no curly braces needed
import Button from './Button.js';

You can rename default imports to anything you want:

import MyButton from './Button.js'; // this also works

Combining both:

// api.js
export default function fetchData() {
/* ... */
}
export function formatResponse() {
/* ... */
}
// Importing
import fetchData, { formatResponse } from './api.js';

Why modules matter

1. Organization — Each file has a clear responsibility. Instead of one giant file, you have many small, focused files.

2. Encapsulation — Variables and functions are private by default. Only what you export is accessible from outside.

3. Reusability — Write a function once, import it wherever you need it. No copy-pasting.

4. Dependency management — By looking at the imports at the top of a file, you immediately know what the file depends on.

5. Tree shaking — Bundlers can remove exports that nobody imports, reducing your final bundle size.

Using modules in the browser

Modern browsers support modules natively. You use type="module" on your script tag:

<script type="module" src="app.js"></script>

Module scripts are:

  • Deferred by default (they wait for the HTML to parse)
  • Strict mode by default (no need for "use strict")
  • Scoped — variables do not leak to the global scope

Dynamic imports

Sometimes you do not want to load a module right away. Dynamic imports let you load modules on demand:

button.addEventListener('click', async () => {
const { Chart } = await import('./chart.js');
const chart = new Chart(data);
chart.render();
});

The chart module is only loaded when the user clicks the button. This is useful for code splitting — it keeps your initial bundle small and loads extra code only when needed.

In React, this is commonly used with React.lazy:

const Chart = React.lazy(() => import('./Chart'));

Interview Tip

When answering this question, explain the problem modules solve (global scope conflicts), how they work (import/export), and the practical benefits (organization, encapsulation, tree shaking). If the interviewer asks about dynamic imports, explain that they are used for code splitting to improve performance. This shows you think about both code organization and user experience.

Why interviewers ask this

Modules are a fundamental part of every modern JavaScript project. Interviewers want to know if you understand how to organize code, if you know the difference between named and default exports, and if you understand the benefits like encapsulation and tree shaking. It is a basic question, but the depth of your answer tells a lot about your experience.