commonjs與es6 中的模塊化機制有什麼區別

名詞解釋

  • cjs(commonjs)

    seaJs和node環境下使用的模塊化機制。模塊必須通過 module.exports 導出對外的變量或接口,通過 require() 來導入其他模塊的輸出到當前模塊作用域中。模塊加載是同步的。

  • amd

    伴隨requireJs提出的異步加載模塊規範。瀏覽器環境下適用,來解決同步加載的問題。

  • es6 module

    es6提出的模塊加載機制。

cjs與es6 module的區別

CommonJs導出的是變量的一份拷貝,ES6 Module導出的是變量的綁定(export default 是特殊的)

cjs中,對象的傳遞如同a = b 一樣,基本類型值傳遞,對象則引用傳遞。而es6 module中,如果不用export default去引用,基本類型也是引用傳遞的。export default的賦值則與a = b 相同。

CommonJs是單個值導出,ES6 Module可以導出多個

一般不提倡使用了export default 還export {a, b, c}。

CommonJs是動態語法可以寫在判斷裏,ES6 Module靜態語法只能寫在頂層

便於靜態檢查。如果有循環引用,cjs可以從緩存裏讀,讀到哪裏就是哪裏。module.exports.a可以改變。而es6則會報錯,只能通過函數的方式來讀值,因爲函數聲明會提升到文件頂部。

靜態檢查有利於搖樹優化。

webpack(當前版本,4.x)要求如果想要搖樹優化,必須用es6的modules寫法。而且注意拿給webpack打包前不能先用Babel轉,因爲這其實是會讓es6的import/export語法變爲cjs的語法,或者在presets中寫清"modules" false:。同時需要在package.json文件中寫清sideEffects。

可以在package.json 加一個 module 的字段來指向 es module規範的文件,main -> CommonJs,那麼module - es module。webpack與rollup都支持這個字段。

CommonJs的 this 和 ES6 Module的 this

es6的module默認就是嚴格模式,因此會得到如下結果:

<script type="module">
  function logThis() {
    console.log(this)
  }
  logThis()  // 結果爲undefined。
</script>

node module中的最外層代碼中,this等於module.exports。所以如果直接打印console.log(this),出來的是{}。如果在箭頭函數中打印this,結果也是如此。

如果在function函數中使用this,其值決定於這個函數是怎麼被執行的。在非嚴格模式下,直接執行函數,this等於global對象。嚴格模式下等於undefined。

在瀏覽器中也是同理。箭頭函數和直接console this,結果都是window。如果在function中使用this,非嚴格模式下,在全局直接執行函數,this等於window,嚴格模式下是undefined。

stackoverflow上的這篇文章:this behaves differently in nodejs and browser下的第一個回答很好地解釋了爲什麼。大意爲,瀏覽器與nodejs不同之處在於,瀏覽器中,所有script都在window下加載,而nodejs則每個script文件都是在它自己的閉包下(一個module一個module)執行。Nodejs會把js文件中的this包裝在一個匿名函數中,爲每個文件(file/module)創建它自己的執行上下文。this處於module scope 而不是 global scope

而如果沒有在調用函數時給定特定的上下文,函數中的this默認會指向全局對象。nodejs中是Global,瀏覽器中就是window。嚴格模式下,均爲undefined。

umd通用

如果打包工具裏指定了打出umd的包,那麼一般可以見到這段代碼:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined'? module.exports = factory() :
  typeof define  === 'function' && define.amd? define(factory) : (global.libName = factory())
})(this, (function() { 'use strict'; }))

這段代碼的作用就是判斷環境,以兼容各種模塊加載方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章