引用:html
//foo.js
exports.foo="foo"
//等同於
module.exports.foo="foo"
//bar.js
const { foo } = require('./foo.js')
console.log(foo);//'foo'
複製代碼
//foo.js
exports={
foo: 'foo'
}
//bar.js
const { foo } = require('./foo.js')
//reuqire 返回的是 module.exports 對象, 默認爲 {}
console.log(foo);//undefined
複製代碼
/*************** a.js**********************/
let count = 0
exports.count = count; // 輸出值的拷貝
exports.add = ()=>{
//這裏改變count值,並不會將module.exports對象的count屬性值改變
count++;
}
/*************** b.js**********************/
const { count, add } = require('./a.js')
//在支持es6模塊的環境下等同於
import { count, add } from './a.js'
console.log(count) //0
add();
console.log(count)//0
複製代碼
/*************** a.js**********************/
export let count = 0;//輸出的是值的引用,指向同一塊內存
export const add = ()=>{
count++;//此時引用指向的內存值發生改變
}
/*************** b.js**********************/
import { count, add } from './a.js'
console.log(count) //0
add();
console.log(count)//1
複製代碼
/*************** a.js**********************/
const foo = {
count: 0
}
//module.exports的foo屬性爲 foo 對象的淺拷貝,指向同一個內存中
exports.foo=foo;
window.setTimeout(()=>{
foo.count += 1
console.log('changed foo')
},1000)
/*************** b.js**********************/
const { foo } = require('./a.js')
console.log('foo', foo);//'foo',{count: 0}
window.setTimeout(()=>{
console.log('after 2s foo', foo);//'after 2s foo ',{count: 1}
}, 2000)
複製代碼
其實上個栗子中的 const { foo } = require('./a.js')
或者 const foo = require('./a.js').foo
寫法是至關危險的。由於commonJs輸出的值的拷貝,若後面在a.js中 對foo的內存指向做出改動,則不能及時更新。es6
咱們將上面的栗子作個小改動:緩存
/*************** a.js**********************/
const foo = {
count: 0
}
exports.foo=foo; //此時foo指向 {count: 0}的內存地址
window.setTimeout(()=>{
//改變 foo 的內存指向
exports.foo='haha';
},1000)
/*************** b.js**********************/
const { foo } = require('./a.js'); //拷貝了 foo屬性指向 {count: 0} 內存地址的引用
console.log('foo', foo);//'foo',{count: 0}
window.setTimeout(()=>{
//看!並無改變!
console.log('after 2s foo', foo);//'after 2s foo ',{count: 0}
}, 2000)
複製代碼
改進:bash
/*************** b.js**********************/
const test = require('./a.js');
//test 拷貝了 整個輸出對象{foo:{count: 0} }內存地址的引用
//當內存中的屬性值發生變化時,能夠拿到最新的值,由於指向的是同一片內存
console.log('foo', test.foo);//'foo',{count: 0}
window.setTimeout(()=>{
//保證獲取到的是最新的
console.log('after 2s foo', test.foo);//'after 2s foo ','haha'
}, 2000)
複製代碼
進階:函數
/*************** child.js**********************/
let foo = 1
setTimeout(()=>{
foo=2;
exports.foo= foo
},1000)
exports.foo=foo
/*******************index.js***************************/
var test =require('./child');
console.log(test.foo);// 1
setTimeout(()=>{
console.log(test.foo) // 2
},2000)
複製代碼
將child.js中的輸出方式作一下改動,結果就變了。ui
/*************** child.js**********************/
let foo = 1
setTimeout(()=>{
foo=2;
module.exports={foo};//注意:指向新內存 {foo:2}
},1000)
module.exports={foo}; //指向內存 {foo:1}
/*******************index.js***************************/
var test =require('./child');// 淺拷貝,指向的仍是{foo:1}的內存,並緩存在內存中
console.log(test.foo);// 1 //從緩存的內存中取值
setTimeout(()=>{
console.log(test.foo) // 1 //從緩存的內存中取值
},2000)
複製代碼
module.exports 等同於 export default 能夠用 import 引入spa
CommonJS 模塊加載 ES6 模塊,不能使用require命令,而要使用import()函數。code
// es.mjs
let foo = { bar: 'my-default' };
export default foo;
// cjs.js
const es_namespace = await import('./es.mjs');
// es_namespace = {
// get default() {
// ...
// }
// }
console.log(es_namespace.default);
// { bar:'my-default' }
複製代碼
參考連接:htm