ES6模块化

这几天在看vuex,模块引入这块看的有些迷,所以看了阮大大关于模块化这部分的教程。然后总结了一些常用的部分。

export

输出可以有两种方式:第三种是用来重命名

1
2
3
4
5
6
7
8
9
10
// 写法一
export var m = 1;

// 写法二
var m = 1;
export {m};

// 写法三
var n = 1;
export {n as m};

下面的写法是不对的:

1
2
3
4
5
6
// 报错
export 1;

// 报错
var m = 1;
export m;

还要注意输出的接口与模块内部对应的值是一个动态绑定的关系:

1
2
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

上面代码输出变量foo,值为bar,500毫秒之后变成baz。

import

使用import来加载模块

1
import {firstName, lastName, year} from './profile';

也可以使用as来更改引入模块的名字

1
import { lastName as surname } from './profile';

整体引入模块而不是只引入模块的一部分,可以把模块内所有的方法依次引入,也可以用*来引入:

1
2
3
4
5
6
7
export function area(radius) {
return Math.PI * radius * radius;
}

export function circumference(radius) {
return 2 * Math.PI * radius;
}
1
2
3
4
import * as circle from './circle';

console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));

这样所有引入模块的方法都挂载到了circle这个对象上面,只需要在circle上取到对应的方法。

ES6模块加载实质

ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。

这句话很重要,CommonJS模块值一旦输出,内部的变化不会影响输出的值。因为他是一个值的拷贝。

而ES6模块是生成一个动态的只读引用,这里有两个重点:动态引用、只读。

动态,模块内部外部是会动态改变的。

1
2
3
4
5
6
7
8
9
10
11
// lib.js
export let counter = 3;
export function incCounter() {
counter++;
}

// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4

只读,可以添加属性,但是不能重新赋值。类似于const

1
2
3
4
5
6
7
8
// lib.js
export let obj = {};

// main.js
import { obj } from './lib';

obj.prop = 123; // OK
obj = {}; // TypeError

export通过接口,输出的是同一个值。不同的脚本加载这个接口,得到的都是同样的实例。

1
2
3
4
5
6
7
8
9
10
11
12
// mod.js
function C() {
this.sum = 0;
this.add = function () {
this.sum += 1;
};
this.show = function () {
console.log(this.sum);
};
}

export let c = new C();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// x.js
import {c} from './mod';
c.add();

// y.js
import {c} from './mod';
c.show();

// main.js
import './x';
import './y';

//执行main.js
//输出1

这就证明的是输出了同一个实例。