commonjs模塊與es6模塊有什么不同?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
為金水等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及金水網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都做網(wǎng)站、網(wǎng)站建設(shè)、金水網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!commonjs
對(duì)于基本數(shù)據(jù)類型,屬于復(fù)制。即會(huì)被模塊緩存。同時(shí),在另一個(gè)模塊可以對(duì)該模塊輸出的變量重新賦值。
對(duì)于復(fù)雜數(shù)據(jù)類型,屬于淺拷貝。由于兩個(gè)模塊引用的對(duì)象指向同一個(gè)內(nèi)存空間,因此對(duì)該模塊的值做修改時(shí)會(huì)影響另一個(gè)模塊。
當(dāng)使用require命令加載某個(gè)模塊時(shí),就會(huì)運(yùn)行整個(gè)模塊的代碼。
當(dāng)使用require命令加載同一個(gè)模塊時(shí),不會(huì)再執(zhí)行該模塊,而是取到緩存之中的值。也就是說,commonjs模塊無(wú)論加載多少次,都只會(huì)在第一次加載時(shí)運(yùn)行一次,以后再加載,就返回第一次運(yùn)行的結(jié)果,除非手動(dòng)清除系統(tǒng)緩存。
循環(huán)加載時(shí),屬于加載時(shí)執(zhí)行。即腳本代碼在require的時(shí)候,就會(huì)全部執(zhí)行。一旦出現(xiàn)某個(gè)模塊被"循環(huán)加載",就只輸出已經(jīng)執(zhí)行的部分,還未執(zhí)行的部分不會(huì)輸出。
ES6模塊
es6模塊中的值屬于【動(dòng)態(tài)只讀引用】。
對(duì)于只讀來(lái)說,即不允許修改引入變量的值,import的變量是只讀的,不論是基本數(shù)據(jù)類型還是復(fù)雜數(shù)據(jù)類型。當(dāng)模塊遇到import命令時(shí),就會(huì)生成一個(gè)只讀引用。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。
對(duì)于動(dòng)態(tài)來(lái)說,原始值發(fā)生變化,import加載的值也會(huì)發(fā)生變化。不論是基本數(shù)據(jù)類型還是復(fù)雜數(shù)據(jù)類型。
循環(huán)加載時(shí),
上面說了一些重要區(qū)別?,F(xiàn)在舉一些例子來(lái)說明每一點(diǎn)吧
commonjs
對(duì)于基本數(shù)據(jù)類型,屬于復(fù)制。即會(huì)被模塊緩存。同時(shí),在另一個(gè)模塊可以對(duì)該模塊輸出的變量重新賦值。
// b.js let count = 1 let plusCount = () => { count++ } setTimeout(() => { console.log('b.js-1', count) }, 1000) module.exports = { count, plusCount } // a.js let mod = require('./b.js') console.log('a.js-1', mod.count) mod.plusCount() console.log('a.js-2', mod.count) setTimeout(() => { mod.count = 3 console.log('a.js-3', mod.count) }, 2000) node a.js a.js-1 1 a.js-2 1 b.js-1 2 // 1秒后 a.js-3 3 // 2秒后
以上代碼可以看出,b模塊export的count變量,是一個(gè)復(fù)制行為。在plusCount方法調(diào)用之后,a模塊中的count不受影響。同時(shí),可以在b模塊中更改a模塊中的值。如果希望能夠同步代碼,可以export出去一個(gè)getter。
// 其他代碼相同 module.exports = { get count () { return count }, plusCount } node a.js a.js-1 1 a.js-2 1 b.js-1 2 // 1秒后 a.js-3 2 // 2秒后, 由于沒有定義setter,因此無(wú)法對(duì)值進(jìn)行設(shè)置。所以還是返回2
對(duì)于復(fù)雜數(shù)據(jù)類型,屬于淺拷貝。由于兩個(gè)模塊引用的對(duì)象指向同一個(gè)內(nèi)存空間,因此對(duì)該模塊的值做修改時(shí)會(huì)影響另一個(gè)模塊。
// b.js let obj = { count: 1 } let plusCount = () => { obj.count++ } setTimeout(() => { console.log('b.js-1', obj.count) }, 1000) setTimeout(() => { console.log('b.js-2', obj.count) }, 3000) module.exports = { obj, plusCount } // a.js var mod = require('./b.js') console.log('a.js-1', mod.obj.count) mod.plusCount() console.log('a.js-2', mod.obj.count) setTimeout(() => { mod.obj.count = 3 console.log('a.js-3', mod.obj.count) }, 2000) node a.js a.js-1 1 a.js-2 2 b.js-1 2 a.js-3 3 b.js-2 3
以上代碼可以看出,對(duì)于對(duì)象來(lái)說屬于淺拷貝。當(dāng)執(zhí)行a模塊時(shí),首先打印obj.count的值為1,然后通過plusCount方法,再次打印時(shí)為2。接著在a模塊修改count的值為3,此時(shí)在b模塊的值也為3。
3.當(dāng)使用require命令加載某個(gè)模塊時(shí),就會(huì)運(yùn)行整個(gè)模塊的代碼。
4.當(dāng)使用require命令加載同一個(gè)模塊時(shí),不會(huì)再執(zhí)行該模塊,而是取到緩存之中的值。也就是說,commonjs模塊無(wú)論加載多少次,都只會(huì)在第一次加載時(shí)運(yùn)行一次,以后再加載,就返回第一次運(yùn)行的結(jié)果,除非手動(dòng)清除系統(tǒng)緩存。
5.循環(huán)加載時(shí),屬于加載時(shí)執(zhí)行。即腳本代碼在require的時(shí)候,就會(huì)全部執(zhí)行。一旦出現(xiàn)某個(gè)模塊被"循環(huán)加載",就只輸出已經(jīng)執(zhí)行的部分,還未執(zhí)行的部分不會(huì)輸出。
3, 4, 5可以使用同一個(gè)例子說明 // b.js exports.done = false let a = require('./a.js') console.log('b.js-1', a.done) exports.done = true console.log('b.js-2', '執(zhí)行完畢') // a.js exports.done = false let b = require('./b.js') console.log('a.js-1', b.done) exports.done = true console.log('a.js-2', '執(zhí)行完畢') // c.js let a = require('./a.js') let b = require('./b.js') console.log('c.js-1', '執(zhí)行完畢', a.done, b.done) node c.js b.js-1 false b.js-2 執(zhí)行完畢 a.js-1 true a.js-2 執(zhí)行完畢 c.js-1 執(zhí)行完畢 true true
仔細(xì)說明一下整個(gè)過程。
在Node.js中執(zhí)行c模塊。此時(shí)遇到require關(guān)鍵字,執(zhí)行a.js中所有代碼。
在a模塊中exports之后,通過require引入了b模塊,執(zhí)行b模塊的代碼。
在b模塊中exports之后,又require引入了a模塊,此時(shí)執(zhí)行a模塊的代碼。
a模塊只執(zhí)行exports.done = false這條語(yǔ)句。
回到b模塊,打印b.js-1, exports, b.js-2。b模塊執(zhí)行完畢。
回到a模塊,接著打印a.js-1, exports, b.js-2。a模塊執(zhí)行完畢
回到c模塊,接著執(zhí)行require,需要引入b模塊。由于在a模塊中已經(jīng)引入過了,所以直接就可以輸出值了。
結(jié)束。
從以上結(jié)果和分析過程可以看出,當(dāng)遇到require命令時(shí),會(huì)執(zhí)行對(duì)應(yīng)的模塊代碼。當(dāng)循環(huán)引用時(shí),有可能只輸出某模塊代碼的一部分。當(dāng)引用同一個(gè)模塊時(shí),不會(huì)再次加載,而是獲取緩存。
ES6模塊
es6模塊中的值屬于【動(dòng)態(tài)只讀引用】。只說明一下復(fù)雜數(shù)據(jù)類型。
對(duì)于只讀來(lái)說,即不允許修改引入變量的值,import的變量是只讀的,不論是基本數(shù)據(jù)類型還是復(fù)雜數(shù)據(jù)類型。當(dāng)模塊遇到import命令時(shí),就會(huì)生成一個(gè)只讀引用。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。
對(duì)于動(dòng)態(tài)來(lái)說,原始值發(fā)生變化,import加載的值也會(huì)發(fā)生變化。不論是基本數(shù)據(jù)類型還是復(fù)雜數(shù)據(jù)類型。
// b.js export let counter = { count: 1 } setTimeout(() => { console.log('b.js-1', counter.count) }, 1000) // a.js import { counter } from './b.js' counter = {} console.log('a.js-1', counter) // Syntax Error: "counter" is read-only
雖然不能將counter重新賦值一個(gè)新的對(duì)象,但是可以給對(duì)象添加屬性和方法。此時(shí)不會(huì)報(bào)錯(cuò)。這種行為類型與關(guān)鍵字const的用法。
// a.js import { counter } from './b.js' counter.count++ console.log(counter) // 2
循環(huán)加載時(shí),ES6模塊是動(dòng)態(tài)引用。只要兩個(gè)模塊之間存在某個(gè)引用,代碼就能夠執(zhí)行。
// b.js import {foo} from './a.js'; export function bar() { console.log('bar'); if (Math.random() > 0.5) { foo(); } } // a.js import {bar} from './b.js'; export function foo() { console.log('foo'); bar(); console.log('執(zhí)行完畢'); } foo(); node a.js foo bar 執(zhí)行完畢 // 執(zhí)行結(jié)果也有可能是 foo bar foo bar 執(zhí)行完畢 執(zhí)行完畢
關(guān)于commonjs模塊與es6模塊有什么不同問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。