其實(shí)是很明顯的一個bug周偎。
項(xiàng)目中有一個入口React組件Root來做一些初始化的工作抹剩,其中包含初始化全局變量,偽代碼如下:
import './Page.js';
class Root extends React.Component {
componentDidMount() {
initGlobal();
}
initGlobal() {
global.isIOS = true;
// ...
}
}
獲取設(shè)備信息deviceInfo.js(在下面的Page.js用到了):
export function getStatusBarHeight() {
if (global.isIOS) {
return 20;
} else {
return 44;
}
}
還有一個頁面組件Page.js(會被加載到):
import { getStatusBarHeight } from './deviceInfo.js';
const statusBarHeight = getStatusBarHeight();
class Page extends React.Component {
render() {
<div style={{paddingTop: statusBarHeight}}></div>
}
}
然后大家應(yīng)該猜到了在Page.js中執(zhí)行getStatusBarHeight()
的時候每次都是44蓉坎,因?yàn)閳?zhí)行的時候global.isIOS
是undefined澳眷。原因是執(zhí)行const statusBarHeight = getStatusBarHeight();
的時候global.isIOS還沒初始化。
我在寫deviceInfo.js的時候心里默認(rèn)global已經(jīng)加載OK了才導(dǎo)致了這個問題蛉艾,這讓我思考后面應(yīng)該如何來避免這個問題:
不要使用全局變量钳踊!全局的變量都放到模塊中衷敌,使用的時候從模塊中加載就不會出現(xiàn)這個問題了。(不用全局變量這個道理大家都知道拓瞪,卻不是每個人都可以做到)
正好趁這個機(jī)會又復(fù)習(xí)了下ES6的模塊的東西缴罗,筆記如下:
ES6的模塊是在編譯的時候就可以確認(rèn)模塊的依賴關(guān)系,AMD只有運(yùn)行的時候才可以確認(rèn)祭埂,所以相比AMD的模塊系統(tǒng)面氓,ES6的模塊系統(tǒng)會有幾個好處(相比AMD之類來說):
- 可以只加載用到的東西,比如
import { every } from 'lodash'
蛆橡,這樣只會把lodash的every方法加載進(jìn)來舌界,而不是加載整個lodash對象。 - 編譯的時候就完成模塊加載泰演,所以執(zhí)行效率更高呻拌。
不能把import用到表達(dá)式,變量和if語句之類的睦焕,因?yàn)檫@些無法通過靜態(tài)檢查藐握,只有運(yùn)行的時候才會得到結(jié)果。但是這樣就限制了動態(tài)加載了垃喊,實(shí)際上現(xiàn)在ES6已經(jīng)有了草案來支持動態(tài)加載了猾普,目前通過babel也可以實(shí)現(xiàn)。
模塊加載順序沒有統(tǒng)一規(guī)范本谜。
參考:
- Module 的語法
- 《你不知道的JavaScript》上卷