谈谈es6的模块化

如今模块化的编程方式,已经成为了每个前端程序员必须掌握的一门技术,es6 也带了 importexport 两个新语法,搞清楚他们的作用和用法也是我们所必须要学习的。

需要注意的一些概念

  • 首先,es6 的模块是基于文件的模块,在浏览器端还不支持 importexport 语法,我们开发过程使用,也是需要通过打包工具将其编译为 es5 的语法才能使用。
  • es6 的模块是单利的,也就是说,模块只有一个实例,每次我们 import 的时候,其实都是同一个对象。如果需要有多个模块实例的话,则需要通过 export 一个工厂方法来实现

语法

es6 模块主要就是两个新的关键字 importexport

named export (命名导出)

1
2
3
4
5
6
7
8
9
10
11
function test() {
}

var awesome = 'awesome';

var name = 'test'

export {
test,
awesome
};

在模块内作用域都是局部的,只要没有 export 出去,外面就无法访问到。

我们也可以在导出的时候给成员重命名 export { test as try }

模块是单例的

1
2
3
4
5
6
7
8
9
10
11
// test.js
let name = 'test';
export {name};

// index.js
import { name } from './test';
name = 'index change it';

// getname.js
import { name } from './test';
console.log(name); // index change it

当我们在 index.js 修改了从 test.js import 进来的 name,之后我们再在 getname.js 中 import 它,这时候我们就会发现这个值就被修改了。

这是因为在 import 的时候,我们本质上可以看做是引了一个对变量的指针。虽然有这个特性,但是我们应该避免使用这个特性,
因为这会增大我们程序的复杂度,会使得程序变得难以维护,追踪变量在哪里被修改是非常麻烦的。

export default (默认导出)

1
2
3
// test.js
const name = 'test';
export default name;

当文件中有默认导出的时候我们可以通过下面几种方式得到这个值

  • import name from './test' 这个 name 也可以叫其他名字比方说import test from './test' 这里 name 和 test 其实指的是同一个东西

  • import { default as name } from './test 这里的 default 不能省略

namespace import (命名空间引入)

1
2
import * as test from './test'
console.log(test.name);

es6 的设计理念是让我们按需引用,不过还是看具体的需要,如果引入的模块比较小的话,
我们还是可以通过使用命名空间引入的方式来进行引用。

import 立执行的函数

1
import 'rxjs/operators/add';

有时候我们会看到一些类似于上面的用法,这些一般加载的是一些立执行的函数,一般我们也要避免使用这种,因为他会导致你的代码变得难以理解,后来的 rxjs6 也修改了这种用法