esm
标准通过import, export
语法实现模块变量的导入和导出。
esm
模块和 commonjs
模块的一个显著差异是:
cjs
导出的是值的拷贝
esm
导出的是值的引用。
当模块内部的值被修改时,cjs
获取不到被修改后的值,esm
可以获取到被修改后的值。
根据个人理解,cjs
导出的时候要看导出的是基本类型还是对象类型,然后才能确定能不能获取到修改后的值:
比如CJS:
修改的是count
基本类型
// 1.js
let count = 1;
function incCount() {
count += 1;
}
module.exports = {
count: count,
incCount: incCount,
};
// 2.js
let { count, incCount } = require("./1.js");
console.log(count); // 1
incCount();
console.log(count); // 1
1
1
修改的person
是对象类型
// 1.js
let count = 1;
let person = {
name: "zs",
};
function incCount() {
count += 1;
person.name += "111";
}
module.exports = {
count,
person,
incCount,
};
// 2.js
let { count, incCount, person } = require("./1.js");
console.log(count, person);
incCount();
console.log(count, person);
1 { name: 'zs' }
1 { name: 'zs111' }
但是ESM不一样,即使我们修改的是count是基本类型:
// 1.mjs
let count = 1;
let person = {
name: "zs",
};
function incCount() {
count += 1;
person.name += "111";
}
export { count, person, incCount };
// 2.mjs
import { count, incCount, person } from "./1.mjs";
console.log(count, person);
incCount();
console.log(count, person);
1 { name: 'zs' }
2 { name: 'zs111' }
ES6 模块的运行机制与 CommonJS
不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import
有点像 Unix 系统的“符号连接”,原始值变了,import
加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
由于 ES6 输入的模块变量,只是一个“符号连接”,所以这个变量是只读的,对它进行重新赋值会报错。
// 2.mjs
import { count, incCount, person } from "./1.mjs";
console.log(count, person);
incCount();
console.log(count, person);
count = "222"; //重新赋值
TypeError: Assignment to constant variable.
还是要看大佬的文章啊,网上看一堆文章不如直接看阮老师的