Export and Import
JavaScript Export and Import (JavaScript导出和导入)
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. (幸运的是, JavaScript可以克服这些困难。导入和导出有助于解决上述问题。)
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
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
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*
Import* (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('w3cdoc'); // Welcome to w3cdoc!
saySoon('w3cdoc'); // See you later on our w3cdoc!
If you intend to import a lot of things, you can do that as an object using import * as <obj>.
Import “as”
Import “as” (导入:)
You can use as for importing under various names. (您可以在各种名称下使用as进行导入。)
Let’s see an example where we import sayWelcome into the local variable welcome, and import seeSoon as soon, for brevity. (让我们看一个示例,其中我们将sayWelcome导入局部变量welcome ,并尽快导入seeSoon ,以保持简洁。)
Here is how it looks like:
// main.js
import {
sayWelcome as welcome,
saySoon as soon
} from './welcome.js';
welcome('w3cdoc'); // Welcome to w3cdoc!
soon('w3cdoc'); // See you later on our w3cdoc!
Export “as”
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('w3cdoc'); // Welcome to w3cdoc!
say.soon('w3cdoc'); // See you later on our w3cdoc!
So, now they become official names for outsiders to be applied for imports. (因此,现在它们成为外来者申请进口的正式名称。)
Export Default
Export Default (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). (模块,包含库,函数包(例如welcome.js )。 模块,声明单个实体(例如, site.js仅导出类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('w3cdoc');
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
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,
(默认为Site ,)
welcome
} from './site.js';
new Site('w3cdoc');
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('w3cdoc');
Disadvantages of Default Exports
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 (再出口)
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
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. (从“./site.js”导出站点是语法错误。 export * from ‘./site.js’只能重新导出命名导出,同时忽略默认导出。)
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
To sum up, we can state that export and import are handy means that can make any programmer’s job much more manageable. They allow organizing and decoupling the code and lead to applications that are much simpler to maintain, understand, or debug. (总而言之,我们可以说导出和导入很方便,可以使任何程序员的工作更容易管理。它们允许组织和解耦代码,并导致应用程序更易于维护、理解或调试。)