export 与 export default 的区别

export 与 export default 的区别

本文将介绍 export 与 export default 的差异性。

1. export default 在一个模块里只能有一个,但是 export 可以有多个

1
2
3
4
5
6
7
8
9
// model.js
let e1 = 'export 1';
let e2 = 'export 2';
let e3 = 'export 3';
let e4 = 'export 4';
export { e2 };
export { e3 };
export { e4 };
export default e1;
1
2
3
4
5
6
7
// 使用模块的run.js
import e1, { e2, e3, e4 } from './model.js';

console.log(e1);
console.log(e2);
console.log(e3);
console.log(e4);
1
2
3
4
5
6
7
run.js运行结果
$ node run.js

export 1
export 2
export 3
export 4

如果在model.js再添加一个export default

1
2
let e5 = 'export e5';
export default e5;
1
2
3
4
5
6
$ node run.js
file:///Users/xxx/workspace/model.js:11
export default e5
^^^^^^^^^^^

SyntaxError: Identifier '.default' has already been declared

2. 模块中通过export 导出的(属性或者方法)可以修改,但是通过export default导出的不可以修改

基本类型:

1
2
3
4
5
6
7
8
9
// model.js
let e1 = 'export 1';
let e2 = 'export 2';
export function modifyFunc() {
e1 = 'export 1 modified';
e2 = 'export 2 modified';
}
export { e2 };
export default e1;
1
2
3
4
5
6
7
// 使用模块的run.js
import e1, { e2, modifyFunc } from './model.js';
console.log(e1);
console.log(e2);
modifyFunc();
console.log(e1);
console.log(e2);
1
2
3
4
5
$ node run.js
export 1
export 2
export 1
export 2 modified

Babel 编译后代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
'use strict';

Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.modifyFunc = modifyFunc;
exports.default = exports.e2 = void 0;
let e1 = 'export 1';
let e2 = 'export 2';
exports.e2 = e2;

function modifyFunc() {
e1 = 'export 1 modified';
exports.e2 = e2 = 'export 2 modified';
}

var _default = e1;
exports.default = _default;

对象

1
2
3
4
5
6
7
8
9
let e1 = { v1: 'v1' };
let e2 = { v2: 'v2' };
export function modifyFunc() {
e1 = { v1: 'v1 modified' };
e1.v1 = 'v1 next modified';
e2 = { v22: 'v2 modified' };
}
export { e2 };
export default e1;
1
2
3
4
5
6
7
// 使用模块的run.js
import e1, { e2, modifyFunc } from './model.js';
console.log(e1);
console.log(e2);
modifyFunc();
console.log(e1);
console.log(e2);
1
2
3
4
5
$ node run.js
{ v1: 'v1' }
{ v2: 'v2' }
{ v1: 'v1' }
{ v22: 'v2 modified' }

Babel 编译后代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
'use strict';

Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.modifyFunc = modifyFunc;
exports.default = exports.e2 = void 0;
// model.js
let e1 = {
v1: 'v1',
};
let e2 = {
v2: 'v2',
};
exports.e2 = e2;

function modifyFunc() {
e1 = {
v1: 'v1 modified',
};
e1.v1 = 'v1 next modified';
exports.e2 = e2 = {
v22: 'v2 modified',
};
}

var _default = e1;
exports.default = _default;

首先需要了解到:

  1. ES6 中模块通过exportexport default暴露出来的属性或者方式并不是普通的赋值或者引用,它们是对模块内部定义的标志符类似指针的绑定。
  2. 对于一个导出的属性或者方法,在什么地方导出不重要,在什么时候导入也不重要,重要的是:访问这这个绑定的时候的当前值。
1
2
3
4
5
6
7
8
9
// model.js
let e1 = 'export 1';
let e2 = 'export 2';
export { e2 };
export default e1;
e1 = 'export 1 modified';
setTimeout(() => {
e2 = 'export 2 modified';
}, 1000);
1
2
3
4
5
6
7
// 使用模块的run.js
import e1, { e2 } from './model.js';
console.log(e1);
console.log(e2);
setTimeout(() => {
console.log('-----later-----', e2);
}, 5000);
1
2
3
4
$ node run.js
export 1
export 2
-----later----- export 2 modified

Babel 编译后代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use strict';

Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.default = exports.e2 = void 0;
// model.js
let e1 = 'export 1';
let e2 = 'export 2';
exports.e2 = e2;
var _default = e1;
exports.default = _default;
e1 = 'export 1 modified';
setTimeout(() => {
exports.e2 = e2 = 'export 2 modified';
}, 1000);

但是,export是绑定到标识符,改变标志符的值,然后访问这个绑定,得到的是新值;export default绑定的是标志符指向的值,如果修改标志符指向另一个值,这个绑定的值不会发生变化。 如果想修改默认导出的值,可以使用export {e1 as default}这种方法。

1
2
3
4
// model.js
let e1 = 'export 1';
export { e1 as default };
e1 = 'export 1 modified';
1
2
3
// 使用模块的run.js
import e1 from './model.js';
console.log(e1);
1
2
3
$ node run.js
export 1 modified

Babel 编译后代码

1
2
3
4
5
6
7
8
9
10
'use strict';

Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.default = void 0;
// model.js
let e1 = 'export 1';
exports.default = e1;
exports.default = e1 = 'export 1 modified';

3. export defaultexport语法差异。

  1. export var e1='...' 是合法语句,但是export default var e2='...'是不合法的(letconst也一样)。

  2. export default可以直接添加标识符导出,例如export default e2;export如果要导出已经声明的表示符,必须使用{},例如export {e1},注意:这里{}不是声明一个对象。

可查看例子源码

作者

Sea

发布于

2021-06-03

更新于

2023-01-10

许可协议

评论