都说es6的导出是引用,commonjs导出是值拷贝,所以我想测试一下:
commonjs
commonjs对引用类型导出:对导出的引用修改,会改变模块的值,且引用了该模块的模块都可以获取最新值
// a.js
module.exports.x = "default1";
setTimeout(() => {
module.exports.x = 6;
}, 4000);
setInterval(() => {
console.log('a',module.exports);
}, 1000);
// b.js
let a = require("./a.js");
setInterval(() => {
console.log('b',a);
}, 1000);
setTimeout(() => {
a.x = "2";
}, 2000);
结果为:
a { x: 'default1' }
b { x: 'default1' }
a { x: '2' }
b { x: '2' }
a { x: '2' }
b { x: '2' }
a { x: 6 }
b { x: 6 }
commonjs对基本数据类型导出:外部修改无效(会脱离指向),内部的修改,无法反映到外部!
// a.js
module.exports = "default1";
setTimeout(() => {
module.exports = 6;
}, 4000);
setInterval(() => {
console.log('a',module.exports);
}, 1000);
// b.js
let a = require("./a.js");
setInterval(() => {
console.log('b',a);
}, 1000);
结果为:
a default1
b default1
a default1
b default1
a default1
b default1
a 6
b default1
es6
对于es6导出的引用类型数据,任何一个地方的更改都会影响别的地方的数据!
// a.js
let x = {name:"default1"};
export let y = {name:"default2"};
export default x;
setTimeout(() => {
x.name = "4";
y.name = "4";
}, 4000);
setInterval(() => console.log("a", x, y), 1000);
// b.js
import x from "./a.js";
import { y } from "./a.js";
setInterval(() => console.log("b", x, y), 1000);
setTimeout(() => {
x.name = "2";
y.name = "2";
}, 2000);
结果:
a {name: 'default1'} {name: 'default2'}
b {name: 'default1'} {name: 'default2'}
a {name: 'default1'} {name: 'default2'}
b {name: 'default1'} {name: 'default2'}
a {name: '2'} {name: '2'}
b {name: '2'} {name: '2'}
a {name: '4'} {name: '4'}
b {name: '4'} {name: '4'}
换成基本类型数据,测试结果:无法在外部改变引入模块的值,因为是只读属性引入的,但是内部改变后可以被外部非默认导出获取到最新值!
// a.js
let x = 'default1';
export let y = 'default1';
export default x;
setTimeout(() => {
x = "4";
y = "4";
}, 4000);
setInterval(() => console.log("a", x, y), 1000);
// b.js
import x from "./a.js";
import { y } from "./a.js";
setInterval(() => console.log("b", x, y), 1000);
setTimeout(() => {
x = "2"; // 报错!提示常量无法赋值
y = "2"; // 报错!提示常量无法赋值
}, 2000);
结果:
a default1 default1
b default1 default1
a default1 default1
b default1 default1
报错了。。。
a default1 default1
b default1 default1
a 4 4
b default1 4
总结
- 在模块导出基本类型数据时,
require
方式无法获取内部最新数据而且修改变量值会脱钩,import
方式外部无法修改模块的数据(只读),但是非默认导出属性可以获取内部最新值。 - 在模块导出引用类型数据时,外部和内部的修改都可以被观测到!