關(guān)于JS模塊化時(shí)循環(huán)加載的那些事兒(二)

關(guān)于JS模塊化時(shí)循環(huán)加載的那些事兒(二)

上一篇文章中介紹了ES6和CommonJS語法分別對(duì)于循環(huán)加載時(shí)的處理情況,本期介紹兩種語法混合使用時(shí)對(duì)于循環(huán)加載的處理。
為什么能夠同時(shí)使用兩種語法呢?這樣歸功于babel插件:@babel/plugin-transform-modules-commonjs,在經(jīng)過插件處理后我們可以同時(shí)使用兩種語法而不會(huì)報(bào)錯(cuò)柜与。
來看一個(gè)比上一期稍微復(fù)雜一點(diǎn)的例子。在a.js中同時(shí)使用了兩種語法,ES6 import導(dǎo)入频鉴,CommonJS module.exports導(dǎo)出,同時(shí)構(gòu)建了一個(gè)a->b->c->a的循環(huán)加載場(chǎng)景
1恋拍、a.js

//a.js  es6 with commonjs
import * as b from './b'
console.log('a.js中的b:', b);

const sayHi = (name) => {
  console.log('Hi,', name);

}
const callFunc = (name) => {
   b.sayBye(name);
}
module.exports={
  sayHi:sayHi,
  callFunc:callFunc
}

2垛孔、b.js

//b.js es6
import * as c from './c'
console.log('b.js中的c:', c);
const sayBye = (name) => {
  console.log('Bye,', name);
}
const callFunc = (name) => {
   c.sayHello(name);
}
export {
  sayBye,
  callFunc
}

3、c.js

//c.js es6
import * as a from './a'
console.log('c.js中的a:', a);
const sayHello = (name) => {
  console.log('Hello,', name);
}
const callFunc = (name) => {
   a.sayHi(name);
}
export {
  sayHello,
  callFunc
}

4施敢、main.js

//main.js es6
import * as a from './a.js'
import * as b from './b.js'
import * as c from './c.js'
const f = () => {
  a.sayHi('zzx')
  b.sayBye('zzx');
  c.sayHello('zzx');
  a.callFunc('zzx')
  b.callFunc('zzx');
  c.callFunc('zzx');
}
export { f }

5.TestImportExport.js

//TestImportExport.js es6
import React from 'react';
import * as testmodule from './test_ES6/main';
function TestImportExport() {
  console.log(testmodule);
  return (
    <div>
      <button onClick={ testmodule.f}>測(cè)試</button>
    </div>
  );
}

export default TestImportExport;

OK,現(xiàn)在來看一看控制臺(tái)的輸出
打開網(wǎng)頁時(shí):


打開網(wǎng)頁時(shí)控制臺(tái)的輸出

從圖中可以看到周荐,c.js中記載進(jìn)來的模塊是一個(gè)帶有default屬性但是沒有任何值的空對(duì)象,而b.js和a.js中加載進(jìn)來的模塊都是正常的僵娃。為什么呢概作?我們來看一看執(zhí)行順序就明白了。
首先是main.js加載a.js,執(zhí)行a.js時(shí)發(fā)現(xiàn)加載了b.js又去執(zhí)行b.js,執(zhí)行b.js時(shí)發(fā)現(xiàn)加載了c.js又去執(zhí)行c.js,此時(shí)a.js還沒執(zhí)行完默怨,module.exports還未完成賦值讯榕,所以此時(shí)控制臺(tái)輸出的a是一個(gè)空對(duì)象,至于default屬性的存在是因?yàn)槭褂昧薸mport語法導(dǎo)入經(jīng)過了babel轉(zhuǎn)換先壕。執(zhí)行完c后返回執(zhí)行b再執(zhí)行a瘩扼,這就是我們看到的輸出順序。
再來看一看點(diǎn)擊按鈕后的控制臺(tái)輸出:


點(diǎn)擊按鈕后的控制臺(tái)輸出

從圖中可以看到垃僚,在執(zhí)行c中的callFunc時(shí)出現(xiàn)錯(cuò)誤集绰,因?yàn)閍在加載時(shí)并沒有真正的值,所以無法執(zhí)行谆棺。
現(xiàn)在我們來修復(fù)一下這個(gè)問題:
對(duì)a.js做一下修改
//a.js  es6
import * as b from './b'
console.log('a.js中的b:', b);

const sayHi = (name) => {
  console.log('Hi,', name);

}
const callFunc = (name) => {
   b.sayBye(name);
}
module.exports={
  sayHi:sayHi,
  callFunc:callFunc
}
//新加ES6語法的導(dǎo)出
export {
  sayHi,
  callFunc
}

OK栽燕,我們?cè)賮砜匆豢纯刂婆_(tái)的輸出:
打開網(wǎng)頁時(shí):


打開網(wǎng)頁時(shí)控制臺(tái)的輸出

從圖中可以看到,修改之后c.js中加載的模塊已經(jīng)和其余a.js改淑、b.js中加載的模塊形式上保持一致了碍岔,但是相應(yīng)的值還是undefined,展開后又能看到真實(shí)的值朵夏,這是混用module.exports和export的結(jié)果蔼啦,babel會(huì)把export轉(zhuǎn)換為commonjs語法,我們來看一下a.js編譯后的代碼:


a.js編譯后的代碼

從圖中可以看到仰猖,babel轉(zhuǎn)換后的代碼中export消失了捏肢,取而代之的是exports,并且在加載b.js之前已經(jīng)給exports賦值callFunc和sayHi并且值為undefined奈籽,所以在c.js中加載a時(shí)顯示出來的就是圖中的結(jié)果,真實(shí)運(yùn)行時(shí)已經(jīng)是執(zhí)行完a.js鸵赫,此時(shí)callFunc和sayHi已被重新賦值衣屏,所有函數(shù)都能正常執(zhí)行。

再來看看點(diǎn)擊按鈕后的結(jié)果:


點(diǎn)擊按鈕后控制臺(tái)的輸出

從圖中可以看到辩棒,所有函數(shù)都能正常運(yùn)行狼忱。
經(jīng)過插件轉(zhuǎn)換后的export會(huì)把所有導(dǎo)出的內(nèi)容都提前賦值為undefined,然后在執(zhí)行到模塊時(shí)重新賦值一睁。修改一下a.js

//a.js  es6 with commonjs
import * as b from './b'
console.log('a.js中的b:', b);

const sayHi = (name) => {
  console.log('Hi,', name);

}
const callFunc = (name) => {
   b.sayBye(name);
}
//增加一個(gè)常量
const name = 'zzx';
module.exports={
  sayHi:sayHi,
  callFunc:callFunc
}
export {
  sayHi,
  callFunc,
  name
}

再來看看編譯后的代碼:


a.js修改后的編譯輸出

此時(shí)打開網(wǎng)頁的控制臺(tái)輸出如下:


修改后的控制臺(tái)輸出

我們?cè)賹?duì)c.js做一下修改钻弄,看一看加載后不立即使用a模塊的情形。修改一下c.js
//c.js es6
import * as a from './a'
console.log('c.js中的a:', a)
setTimeout(()=>{console.log('c.js中的a(1ms以后):', a)},1);
const sayHello = (name) => {
  console.log('Hello,', name);
}
const callFunc = (name) => {
   a.sayHi(name);
}
export {
  sayHello,
  callFunc
}

來看看此時(shí)的控制臺(tái)輸出


c.js修改后的輸出

從圖中可以看到卖局,加載模塊后立即使用是只有exports提前賦值的值斧蜕,而在模塊全部加載完之后再使用是OK的。

綜上所述砚偶,babel插件會(huì)把ES6語法轉(zhuǎn)換為CommonJS語法并且做一些額外的操作(如提前賦值)以保證轉(zhuǎn)換后的表現(xiàn)與ES6語法期待的表現(xiàn)一致批销,出現(xiàn)循環(huán)加載時(shí)可以正常運(yùn)行,除非你在加載模塊后立即使用染坯。
本期介紹暫告一段落均芽,下期一起去看一看webpack對(duì)模塊時(shí)如何加載管理的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末单鹿,一起剝皮案震驚了整個(gè)濱河市掀宋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仲锄,老刑警劉巖劲妙,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異儒喊,居然都是意外死亡镣奋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門怀愧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侨颈,“玉大人,你說我怎么就攤上這事芯义」福” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵扛拨,是天一觀的道長耘分。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么陶贼? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任啤贩,我火速辦了婚禮待秃,結(jié)果婚禮上拜秧,老公的妹妹穿的比我還像新娘。我一直安慰自己章郁,他們只是感情好枉氮,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著暖庄,像睡著了一般聊替。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上培廓,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天惹悄,我揣著相機(jī)與錄音,去河邊找鬼肩钠。 笑死泣港,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的价匠。 我是一名探鬼主播当纱,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼踩窖!你這毒婦竟也來了坡氯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤洋腮,失蹤者是張志新(化名)和其女友劉穎箫柳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啥供,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悯恍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滤灯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坪稽。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鳞骤,靈堂內(nèi)的尸體忽然破棺而出窒百,到底是詐尸還是另有隱情,我是刑警寧澤豫尽,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布篙梢,位于F島的核電站,受9級(jí)特大地震影響美旧,放射性物質(zhì)發(fā)生泄漏渤滞。R本人自食惡果不足惜贬墩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妄呕。 院中可真熱鬧陶舞,春花似錦、人聲如沸绪励。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疏魏。三九已至停做,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間大莫,已是汗流浹背蛉腌。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留只厘,地道東北人烙丛。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像懈凹,于是被迫代替她去往敵國和親蜀变。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容