Default Exports vs Named Exports
Default and named exports differ in syntax, import semantics, and how module APIs are consumed. A module can have one default export and multiple named exports, and the corresponding import syntax is different.
A named export gives a value an explicit exported name. You create one with `export const`, `export function`, `export class`, or an `export { name }` statement, and imports normally use the same exported identifier inside braces, such as `import { add } from './math.js'`.
A default export represents the module's primary exported value. A module can have at most one default export, written with `export default`. The importer can choose the local name, so `export default function add() {}` can be imported as `import calculate from './math.js'`.
The two forms also differ when importing several values. Named imports use braces and can be combined: `import { add, subtract } from './math.js'`. A default import does not use braces, and it can be combined with named imports: `import calculate, { format } from './module.js'`.
Named exports can be aliased during import with `import { add as sum } from './math.js'`. Default exports do not require an alias because the importing code directly chooses the local binding name. This makes default exports convenient for a module centered around one primary value, while named exports make individual API names explicit.
You can also import an entire module namespace with `import * as math from './math.js'`; its named exports become properties such as `math.add`, while the default export is available as `math.default`. Namespace imports are useful when you want to access several exports through one module object.
Key points
- A module can have only one default export but can have multiple named exports.
- Named imports use braces, such as `import { add } from './math.js'`.
- Default imports omit braces, such as `import add from './math.js'`.
- The local name of a default import can be chosen freely; named imports normally preserve the exported name unless aliased.
- Default and named exports can be imported together from the same module.
Interview questions
What is the difference between a default export and a named export?
A named export has an explicit exported identifier and is normally imported with braces. A default export is the module's single default value and is imported without braces. The local name of a default import can be chosen by the importer. A module may have multiple named exports but only one default export.
How would you import a default export and two named exports from the same module?
Put the default import first, followed by a comma and a braced list of named imports. For example, `import App, { Button, Input } from './ui.js'`. The default binding can have any local name, while `Button` and `Input` refer to their corresponding named exports unless aliases are specified.
Can you rename a named import?
Yes. Use the `as` keyword inside the import braces, such as `import { add as sum } from './math.js'`. `add` is the exported name, while `sum` is the local binding used by the importing module. This is useful when two modules expose the same name or when a local name is clearer.
Can a JavaScript module have both default and named exports?
Yes. A module may provide one default export alongside any number of named exports. For example, a component could be the default export while helper functions are named exports. Consumers can import the default value, named values, or both depending on what they need.
What does `import * as utils from './utils.js'` do?
It creates a module namespace binding named `utils`. The namespace exposes the module's exported bindings as properties, such as `utils.format` for a named export. If the module has a default export, it is represented as `utils.default`. This approach is useful when code intentionally wants to group access to many exports under one namespace.