ES6的module, import與export

ES6推出的module系統是除了let、const等變數宣告之外,用來避免全域變數的干擾的利器。試想$符號代表jQuery,而 _ (底線符號)代表的是underscore還是lodash?

舊版本的js,命名與作用域確實挺傷腦筋的。

ES6的module系統提出了幾個關鍵字: import、export、default、from、as以及搭配的符號,用法其實不難。

1
2
3
4
5
6
7
8
9
10
11
// foo.js
export default const Hello = (name) => {
console.log(`Hello ${name}`);
}
// bar.js
import Hello from './foo';
Hello('Peter');
// Hello Peter

我們用export default的方式將方法Hello匯出,default表示Hello是這個module預設的名稱,因此相對應的import就直接使用該名稱載入。也可以export匿名函數,import的時候也可以更改名稱,避免與載入的檔有相同的名稱:

1
2
3
4
5
6
7
8
9
10
11
12
// foo.js
export default function() {
console.log('隨便秀一個!');
}
// bar.js
import Whatever from 'foo';
// 用Whatever來接收foo.js裡面的export default
Whatever();
// => 隨便秀一個!

通常一個module中往往會有多個需要匯出的function,我們也可以這樣做,例如:

1
2
3
4
5
6
7
8
9
10
11
12
// foo.js
export const Hello = (name) => {
console.log(`Hello ${name}`);
}
export const HowOld = (age) => {
console.log(`I'm ${age} years old.`);
}
// bar.js
import {Hello, HowOld} from './foo';

不過每次都需要打export這個關鍵字也很麻煩,或者不是每個function都要export,上述做法會很難管理,可以將程式碼改為:

1
2
3
4
5
6
// foo.js
export { Hello, HowOld };
// bar.js
import { Hello, HowOld } from './foo';

也有另一種方式寫起來相當直覺,就是搭配as與*符號:

1
2
3
4
5
6
7
8
9
10
11
// foo.js
export { Hello, HowOld };
// bar.js
import * as Greeting from './foo';
Greeting.Hello('Peter');
// => Hello Peter
Greeting.HowOld(20);
// => I'm 20 years old.

這樣的方式也非常直覺好用。

ES6的class也是可以export的方式,用法也是一樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// foo.js
export default class Person {
constructor(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
greeting() {
console.log("I am `${this.name}`, I am `${this.age}` years old.");
}
}
// bar.js
import Person from './foo';
let someOne = Person.new('Peter', 25, 'male');
someOne.greeting();
// => I am Peter, I am 25 years old.

如果一個module內有多個class要export,也可以用大夸號的方式:

1
2
3
4
5
6
7
8
// foo.js
class Person {...省略}
class Vehicle {...省略}
export {Person, Vehicle};
// bar.js
import {Person, Vehicle} from './foo';

在react.js中,最常看到的大概是:

1
2
3
4
5
6
import React from 'react';
// 使用 class Abc extends React.Component {...}
import { Component } from 'react';
// 直接使用 class Abc extends Component {...}