调整字号

ES6 快速上手:模块

es6-small

ES6 引入了原生的模块支持。

一个 ES6 模块就是一个 JS 文件,除了以下两个区别:

  • 会自动开启严格模式
  • 可以使用 importexport 关键字

ES6 模块还有一些特点:

  • 模块中声明的变量都是私有的,即使在最外层作用域声明
  • 在模块最外层,this 指向 undefined

模块中声明的变量,默认都是私有的。如果要暴露给其他模块使用,需要 export

// mod1.js
export function foo(a, b, c) {
  ...
}
export class Bar() {
  ...
}

export 可以用在 function, class, var, let, const 前。如果输出的是上例中的 functionclass 声明,则必须有函数名或类名,不能匿名。

如果想要一次性导出多个接口,也可以这样写:

export {foo, bar};

export 语句必须放在最外层,也就是,不能在语句块中 export

import 用来导入模块:

import {foo} from "mod1.js";

或者,导入多个接口:

import {foo, bar} from "mod1.js";

mod1.js会被提前导入并加载。注意导入以后生成的变量 foobar 都是常量,类似 const。所以你不能再声明一个同名变量,或者修改 foobar

你也可以将模块的所有接口整个导入:

import * as myModule from "mod1.js";

这样 mod1.js 的所有接口都被绑定在了 myModule 对象上。你可以在 myModule 上调用 myModule.foo()

不管被导入多少次,一个模块内的代码始终只执行一次:

import { foo } from "mod1.js";
import { bar } from "mod1.js";

重命名接口

导入时,可以给接口重命名:

import {foo as bar} from "mod1.js";

导出时也可以:

export {
  foo as foo1,
  bar as bar2
};

重命名以后,只能使用新的名字。

default

每个 ES6 模块可以有一个默认导出,使用的是 default 关键字:

export default function(a, b) {
  ...
}

export default 关键字后可以跟随任何值。使用 default 时,函数可以是匿名的。

你也可以指定某一个变量为 default

let myObject = {
  foo() {
    return "foo...";
  },
  bar: 66
};
export {myObject as default};

要将一个模块的默认导出 import 进来:

import myModule from "mod1.js";

注意 myModule 没有了花括号。此时在 myModule 上就可以调用 foobar 了。

这种设计是为了与已存在的 CommonJS 和 AMD 模块相兼容。以 jQuery 为例:

import $ from "jquery";

一个模块只能有一个默认导出。但也可以同时存在非默认的导出:

// mod2.js
export let a = 123;
export default function(b, c) {
  ...
}

可以这样把两者一同导入进来:

import foo, { bar } from "mod2.js";

注意非默认的导出总是有一对花括号。默认导出也可以放进括号里,下面语句是同样的作用:

import { default as foo, bar } from "mod2.js";

export ... from

这个语法的作用是把一个模块的导出当作自己的导出,也就是”借用“。例:

export { foo } from "mod1.js";

相当于:

import { foo } from "mod1.js";
export { foo };

有一个微小的区别,就是第二种写法中 foo 被导入进来,已经可以使用 foo 了,而第一种写法 foo 其实并没有被声明,它只是一种“再导出”。

导出时,可以重命名:

export { foo as bar } from "mod1.js";

导出它的所有接口:

export * from "mod1.js";

注意,如果 mod1.js 含有一个默认导出,它也会被当作本模块的默认导出。于是,本模块就不能再使用 export default 了。

无导出的模块

有的模块没有导出,只修改了内置对象,比如:

// unique.js
Array.prototype.unique = function() {
  ...
}

只是往 Array 类型上添加了一个方法。上述文件也可以当成一个模块,尽管它不 import 也不 export。这种模块调用时,可以这样写:

import from "unique.js";
flight