溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS中ESModule和commonjs的使用區(qū)別是什么

發(fā)布時間:2022-07-27 10:11:47 來源:億速云 閱讀:171 作者:iii 欄目:開發(fā)技術

今天小編給大家分享一下JS中ESModule和commonjs的使用區(qū)別是什么的相關知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    ES Module

    導出

    僅導出
    • named exports: 命名導出,每次可以導出一個或者多個。

    • default exports: 默認導出,每次只能存在一個。

    以上兩者可以混合導出:

        // 命名導出
        export const b = 'b'
        // 默認導出
        export default {
          a: 1
        };
    
        const c = 'c'
        export { c }
        
        // 以上內(nèi)容會合并導出,即導出為: {b:'b', c:'c', default: {a:1}}

    更多示例可以直接去看mdn

    重導出(re-exporting / aggregating)

    算是一個導入再導出的一個語法糖吧。

      export {
        default as function1,
        function2,
      } from 'bar.js';
    
      // 等價于
      import { default as function1, function2 } from 'bar.js';
      export { function1, function2 };

    然而這種語法是會報錯的:

    export DefaultExport from 'bar.js'; // Invalid

    正確的語法應該是:

    export { default as DefaultExport } from 'bar.js'; // valid

    我猜是因為export 本身支持的export xxx這種語法必須是要導出一個對象,然而import xxx可能是任意類型,兩者沖突了,所以從編譯層面就不讓這種語法生效會更好。

    嵌入式腳本

    嵌入式腳本不可以使用export。

    引入

    語法
    • import all exports: import * as allVar,所有導出內(nèi)容,包含命名導出及默認導出。allVar會是一個對象,默認導出會作為allVar的key名為default對應的值。

    • import named exports: import {var1, var2},引入命名導出的部分。沒找到,對應的值就為undefined。個人覺得可以看做是"import all exports"的解構語法。

    • import default exports: import defaultVar,引入默認導出的部分。

    • import side effects: import "xxx./js",僅運行這個js,可能是為了獲取其副作用。

        // test.js
        export const b = 'b'     // 命名導出
        export default {    // 默認導出
          a: 1
        };
    
        // index.js
        import { b, default as _defaultModule } from './test.js'
        import defaultModule from './test.js'
        import * as allModule from './test.js'
    
        console.log('name export', b) // 'b'
        console.log('default export', defaultModule) // {a:1}
        console.log(_defaultModule === defaultModule) // true
        console.log('all export', allModule) // {b:'b', default: {a:1}}

    一個之前老記錯的case

        // test.js
        export default {    // 默認導出
          a: 1
        };
    
        // index.js
        import { a } from './test.js'
        console.log('name export', a) // undefined
    
        // index.js
        import defaultModule from './test.js'
        import * as allModule from './test.js'
        console.log('default export', defaultModule) // {a:1}
        console.log('all export', allModule) // {default: {a:1}}
    嵌入式腳本

    嵌入式腳本引入modules時,需要在script上增加 type="module"。

    特點

    live bindings:

    • 通過export在mdn上的解釋,export導出的是live bindings,再根據(jù)其他文章綜合判斷,應該是引用的意思。即export導出的是引用。

    • 模塊內(nèi)的值更新了之后,所有使用export導出值的地方都能使用最新值。

    read-only:通過import在mdn上的解釋,import使用的是通過export導出的不可修改的引用

    strict-mode:被引入的模塊都會以嚴格模式運行。

    靜態(tài)引入、動態(tài)引入

    import x from這種語法有syntactic rigid,需要編譯時置于頂部且無法做到動態(tài)引入加載。如果需要動態(tài)引入,則需要import ()語法。有趣的是,在mdn上,前者分類到了 Statements & declarations, 后者分類到了 Expressions & operators。這倆是根據(jù)什么分類的呢?

      true && import test from "./a.js";
      // SyntaxError: import can only be used in import() or import.meta
      // 這里應該是把import當成了動態(tài)引入而報錯

    示例:

      // a.js
      const test = {
        a: 1
      };
      export default test;
      // 改動模塊內(nèi)部的值
      setTimeout(() => {
        test.a = 2;
      }, 1000);
    
      // index.js
      import test from './index.js'
    
      /* live bindings */
      console.log(test) // {a:1}
      setTimeout(()=>{
        console.log(test) // {a:2}
      }, 2000)
    
      /* read-only */
      test= { a: 3 } // 報錯, Error: "test" is read-only.
    
      /* syntactically rigid */
      if(true){
        import test from './index.js' // 報錯, SyntaxError: 'import' and 'export' may only appear at the top level
      }

    commonJS

    導出

    在 Node.js 模塊系統(tǒng)中,每個文件都被視為獨立的模塊。模塊導入導出實際是由nodejs的模塊封裝器實現(xiàn),通過為module.exports分配新的值來實現(xiàn)導出具體內(nèi)容。

    module.exports有個簡寫變量exports,其實就是個引用復制。exports作用域只限于模塊文件內(nèi)部。 原理類似于:

    // nodejs內(nèi)部
    exports = module.exports
    
    console.log(exports, module.exports) // {}, {}
    console.log(exports === module.exports) // true

    注意:nodejs實際導出的是module.exports,以下幾種經(jīng)典case單獨看一下:

    case1:

    // ?使用exports
    exports.a = xxx
    console.log(exports === module.exports) // true
    
    // ?等價于
    module.exports.a = xxx

    case2:

    // ?這么寫可以導出,最終導出的是{a:'1'}
    module.exports = {a:'1'}
    
    console.log(exports, module.exports) // {}, {a:'1'}
    console.log(exports === module.exports) // false
    
    
    // ?不會將{a:'1'}導出,最終導出的是{}
    exports = {a:'1'}
    
    console.log(exports, module.exports) // {a:'1'}, {}
    console.log(exports === module.exports) // false

    引入

    通過require語法引入:

    // a是test.js里module.exports導出的部分
    const a = require('./test.js')

    原理偽代碼:

    function require(/* ... */) {
      const module = { exports: {} };
      ((module, exports) => {
        // Module code here. In this example, define a function.
        function someFunc() {}
        exports = someFunc;
        // At this point, exports is no longer a shortcut to module.exports, and
        // this module will still export an empty default object.
        module.exports = someFunc;
        // At this point, the module will now export someFunc, instead of the
        // default object.
      })(module, module.exports);
      return module.exports;
    }

    特點

    值拷貝
    // test.js
    let test = {a:'1'}
    setTimeout(()=>{
      test = {a:'2'}
    },1000)
    module.exports = test
    
    // index.js
    const test1 = require('./test.js')
    console.log(test1) // {a:1}
    setTimeout(()=>{
      console.log(test1) // {a:1}
    },2000)

    ES Module和 commonJS區(qū)別

    語法:

    exports、module.exportsrequire 是Node.js模塊系統(tǒng)關鍵字。

    export、export defaultimport 則是ES6模塊系統(tǒng)的關鍵字:

    原理:

    exports、module.exports導出的模塊為值復制。

    export、export default為引用復制。

    時機:

    ES Module靜態(tài)加載是編譯時確定,ES Module動態(tài)加載是運行時確定。

    CommonJS是運行時確定。

    以上就是“JS中ESModule和commonjs的使用區(qū)別是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業(yè)資訊頻道。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

    AI