ES6 module

发表于: 2016-01-30分类于:JavaScript

JavaScript 之前没有原生的模块管理系统,而如今 es6 中包含了 import 和 export 指令用于模块管理。下面来看看如何使用这两个命令。

开始之前先看个使用 import 和 export 的代码片段。

// a.js
var a = 1;
var b = 2;

export { a,b };
// b.js
import {a,b} from './a';
console.log(a,b); // 1,2

导入模块的时候是最后的字符串是模块的所在位置,最后不使用 .js 后缀。

export

模块是用文件来划分的,在一个 js 文件中定义了很多函数、很多变量,最后可以选择导出部分函数与变量让其可以被其他引用该模块的模块使用到,这个时候就可以使用 export 命令。

// person.js
var Person = function(){
    //...
}
var version = '1.0.0';

export {
    Person,
    version
}

上面代码定义了一个构造函数 Person 以及一个表示版本号的字符串,在代码最后导出了它们。下面看看如何引入这个模块。

// student.js
import {Person,version} from './person';

var james = new Person();
// ...

student.js 中使用 import 命令导入了模块。这里需要注意的是 es6 中的模块与 Node 有所差别。在 Node 中导入的是模块的 module.exports 对象,所以可以访问该模块上的所有内容。但是在 es6 中,对于上面 person.js 的导入不能像下面这样:

// Error
import person from './person';

var james = new person.Person();

我们可能会想当然地认为 person.js 中是导出了一个对象,这个对象上面包含 Personversion ,然而实际情况并不是这样的。所以在导入模块的时候需要确切地知道模块中有哪些内容然后使用 import {Person,version} from './person'; 这样的形式来导入。

但是有的时候一个模块导出了太多的东西,如果使用上面这样的方法的,如果导出模块上的所有可以导出的项目,那么会导致顶级作用域上有很多变量或函数。其实我们可以给采用另外一种写法来避免这样的情况。

import * as person from './person';

var james = new person.Person();

上面代码使用了 * 号 和 as 这是说,导出模块 person 中的所有内容,并将它们挂在 person 上面。这样上面的代码就可以正常工作了。

export default

通过上面的几个代码片段可以看出在模块导出的时候需要使用 export {} 这样的语法,花括号中为希望导出的内容。有的时候可能希望导出的是一个对象,这个时候如果使用这样的语法,在模块导入的时候同样使用花括号这样的方法就显得有一些麻烦了,这个时候就到了 export default 大显身手的时候了。

看下面的代码片段:

var util = {};
util.each = function(){};
util.map = function(){};
//...

export default util;

上面代码片段中定义了一个对象,在这个对象上面添加了一些工具方法,最后使用 export default 导出这个对象。在使用这个模块的文件中可以这样写:

import util from './util';

util.each([1,2,3],(val) => console.log(val));

其实上面的代码中不一定在导入的时候是一 util 这个变量,任意合法的变量都是可以的。如:

import tools from './util';

tools.each([1,2,3],(val) => console.log(val));

也就是说 export default 可以导出一个单独的对象、变量、函数、类等等。而且在导入的时候可以将其重命名为其他的名字,不用严格使用模块定义的时候的名字。

import

前面介绍 export 的时候已经穿插着介绍了一些关于 import 的内容了,下面再补充一些:

通常导入的格式与被导入模块导出的方式有关:

// a.js
var a = 1;
var b = 2;
export {
    a,
    b
}
// b.js
import {a,b} from './a';
// 使用 a,b
console.log(a , b); // 1 , 2

// 或者

import * as obj from './a';
// 使用 a,b
console.log(obj.a , obj.b); // 1 , 2

另一种方式:

// a.js
var a = 1;
export default a;
// b.js
import A from './a';

// 这里的 A 是 a.js 中的 a
console.log(A); // 1

别名

在导入和导出的时候均可以使用别名,举例子如下:

// string.js
var loooooong = 'a long string';
var short = 'short';

export {
    loooooong as long,
    short
};

在导出的时候使用 as 来改变导出内容的名字。在导入的时候就要使用 import {long} from './string' 来完成导入。

同样的,可以在导入的时候修改名字。

import {long as veryLong,short} from './string';
console.log(long); // 'a long string'

在导入的时候又将名字 ‘long’ 修改为了 veryLong

还有一种之前已经见过了:

import * as str from './string';

console.log(str.long , str.short);

补充

如果一个模块没有什么可以导的,只想它被执行,那么在导入的时候可以像下面这样写:

// a.js
console.log('start');

在 b.js 开始前先执行 a.js 中的内容

// b.js
import './a';