Export and Import
Having a complex application makes developers scroll through hundreds and thousands of lines of code, which makes it harder for them to debug or even understand the app.
Luckily, JavaScript allows overcoming such difficulties. Having import and export helps one out of the problems above.
There are several syntax options for export and import directives. In the chapter Modules, we have already considered their simple use. Now, we are going to explore more complex examples.
Export Before Declarations¶
It is possible to label any declaration just as exported by putting export before it: no matter it’s a function, variable, or a class.
All the exports in the example below are valid:
// export an array
export let week = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
// export a constant
export const MODULES_BECAME_STANDARD_YEAR = 2020;
// export a class
export class Site {
constructor(siteName) {
this.siteName = siteName;
}
}
Please, take into consideration that export before a class or a function doesn’t transform it into a function expression. It remains a function declaration, although exported.
It is not recommended to use semicolons after function and class declarations. For that reason, you don’t need a semicolon at the end of export class and export function .
Here is a case in point:
export function sayWelcome(site) {
console.log(`Welcome to ${site}!`);
} // no ; at the end
Export Apart from Declarations¶
It is possible to place export independently.
The first step should be declaring and then exporting.
Let’s demonstrate it in the following example:
// welcome.js
function sayWelcome(site) {
console.log(`Welcome to ${site}!`);
}
function saySoon() {
console.log(`See you later on our ${site}!`);
}
export {
sayWelcome,
saySoon
}; // a list of exported variables
Import*¶
For importing, it is usually necessary to put a list of what to import in curly braces, like here:
// main.js
import {
sayWelcome,<
saySoon
} from '.welcome.js';
sayWelcome('Web'); // Welcome to Web!
saySoon('Web'); // See you later on our Web!
If you intend to import a lot of things, you can do that as an object using import * as <obj>.
Import “as”¶
You can use as for importing under various names.
Let’s see an example where we import sayWelcome into the local variable welcome, and import seeSoon as soon, for brevity.
Here is how it looks like:
// main.js
import {
sayWelcome as welcome,
saySoon as soon
} from './welcome.js';
welcome('Web'); // Welcome to Web!
soon('Web'); // See you later on our Web!
Export “as”¶
For export, as the syntax, similar to the one used above, is generally used.
In another case, let’s export the welcome and soon functions:
// welcome.js
...
export {
sayWelcome as welcome, seeSoon as soon
};
// main.js
import * as say from './welcome.js';
say.welcome('Web'); // Welcome to Web!
say.soon('Web'); // See you later on our Web!
So, now they become official names for outsiders to be applied for imports.
Export Default¶
In practice, there exist two types of modules.
- Modules, containing a library, pack of functions ( for example, welcome.js).
- Modules, declaring a single entity ( for example, site.js exports only class Site).
The second approach is preferred most of the time.
As a rule, that requires many files. The reason is that everything needs its own module. Actually, it becomes easier to navigate the code when files are structured into folders and are well-named.
The modules have unique export default syntax for making the “one thing per module” appear better.
Let’s consider an example where export default is put before the entity:
// site.js
export default class Site { // just add "default"
constructor(siteName) {
this.siteName = siteName;
}
}
There can be only a single export default per file.
The next step is importing it without the curly braces, like this:
// main.js
import Site from './site.js'; // not {Site}, just Site
new Site('Web');
Actually, it looks much nicer without using curly braces.
But, forgetting about the curly braces at all is a common mistake. So, it would be best if you remembered that import requires curly braces for named exports and doesn’t need them for the default ones.
Take a look at this case:
Named export | Default export |
---|---|
export class Site { … } | export default class Site { … } |
import { Site } from... | import Site from... |
Technically, it is possible to have both named and default exports in a single module, but usually, developers avoid mixing them.
The examples of perfectly valid default exports look like this:
export default class { // no class name
constructor() { ...
}
}
export default function (site) { // no function name
console.log(`Welcome to ${site}!`);
}
// export a single value, without making a variable
export default ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
It is fine not to give a name, as export default is one for each file, so import without curly braces knows exactly what to import. An export like that will lead to an error without default, like here:
export class { // Error! ,non-default export
constructor() {}
}
The “default” Name¶
There can be situations when the default keyword is used for referencing the default export.
Here is an example of exporting a function distinctly from its definition:
function welcome(site) {
console.log(`Welcome to ${site}!`);
}
// same as if we added "export default" before the function
export { welcome as default };
Let’s consider another example, in which a module site.js exports a single main “default” thing along with several named ones:
// site.js
export default class Site {
constructor(name) {
this.name = name;
}
}
export function welcome(site) {
console.log(`Welcome to ${site}!`);
}
In the example below, the default export with a named export is imported:
// main.js
import {
default as Site,
welcome
} from './site.js';
new Site('W3Docs');
Finally, if you try to import everything * as an object, the default property will be exactly the default export, like here:
// main.js
import * as site from './site.js';
let Site = site.default; // the default export
new Site('W3Docs');
Disadvantages of Default Exports¶
Default exports are straightforward: they name whatever they import.
Moreover, they enforce a developer to use the right name to import, like this:
import {
Site
} from './site.js';
// import {MySite} won't work, the name must be {Site}
On the contrary, for a default export, the name can be chosen when importing, as follows:
import Site from './site.js'; // works
import MySite from './site.js'; // works too
// could be import anything, and it'll still work
It allows team members to use different names for importing the same things. That’s not a good practice.
For avoiding that and keeping the code consistent, you need to follow a rule, according to which imported variables should match with the file names, like here:
import Site from './site.js';
import func from '/path/to/func.js';
...
Still, in some circles, it’s considered a serious disadvantage of default exports. That’s why using named exports is preferable. Even in case only one thing is exported, it’s still done under an exact name without default.
There is another way of doing it easier: it’s re-export.
Re-export¶
Re-export allows you to import things and instantly export them ( also, under a different name).
The syntax of re-export looks like this:
export ... from ...
To make it more obvious, let’s see an example of the re-export:
export {
welcome
}
from './welcome.js'; // re-export welcome
export {
default as Site
}
from './site.js'; // re-export default
Re-exporting the Default Export¶
The default export requires independent handling while re-exporting. Imagine, you have site.js and wish to re-export class Site from it, like this:
// site.js
export default class Site {
// ...
}
Consider two important facts:
- The export Site from './site.js' is a syntax error.
- export * from './site.js'can only re-export named exports, ignoring the default one at the same time.
For re-exporting both the default and named export, two statements are required. The case of re-exporting the default and named export is visualized in the example below:
export * from './site.js'; // to re-export named exports
export {
default
}
from './site.js'; // to re-export the default export
0 Comments
CAN FEEDBACK
Emoji