更重要的区别在于:export default 导出值,而export const/export var/export let 导出引用(或称为实时绑定)。在nodejs中尝试以下代码(使用13或更高版本默认启用es模块):
// a.mjs
export let x = 5;
// or
// let x = 5;
// export { x }
setInterval(() => {
x++;
}, 1000);
export default x;
// index.mjs
import y, { x } from './1.mjs';
setInterval(() => {
console.log(y, x);
}, 1000);
# install node 13 or above
node ./index.mjs
我们应该得到以下输出:
6 5
7 5
8 5
...
...
为什么我们需要这种差异
很可能,export default 用于commonjs module.exports 的兼容性。
如何使用 bundler(rollup, webpack) 实现这一目标
对于上面的代码,我们使用 rollup 来打包。
rollup ./index.mjs --dir build
以及构建输出:
// build/index.js
let x = 5;
// or
// let x = 5;
// export { x }
setInterval(() => {
x++;
}, 1000);
var y = x;
setInterval(() => {
console.log(y, x);
}, 1000);
请注意var y = x声明,即default。
webpack 有类似的构建输出。当添加大量模块构建时,拼接文本是不可持续的,bundlers 将使用Object.defineProperty 来实现绑定(或在 webpack 中称为和谐导出)。请在下面的代码中找到详细信息:
main.js
...
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
...
// 1.js
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[1],[
/* 0 */,
/* 1 */
/***/ (function(__webpack_module__, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "x", function() { return x; });
let x = 5;
// or
// let x = 5;
// export { x }
setInterval(() => {
x++;
}, 1000);
/* harmony default export */ __webpack_exports__["default"] = (x);
/***/ })
]]);
请找出/* harmony export (binding) */ 和/* harmony default export */ 之间的区别行为。
ES 模块原生实现
es-modules-a-cartoon-deep-dive by Mozilla 讲述了 es 模块的原因、内容和方法。