module.exports、exports、export、export default之間的關係和區別

  • 2019 年 11 月 4 日
  • 筆記

對於module.exports、exports和export、export default之間的關係以及他們的區別一直處於懵逼狀態的小夥伴,本篇文章帶你走進新大陸。    首先我們要明白一個前提,CommonJS模組規範和ES6模組規範完全是兩種不同的概念。此處會產生一個疑問,為什麼會出現模組化這種東西,模組化規範又是指的什麼?    :很久以前,開發網頁要通過命名空間的方式來組織程式碼,例如 jQuery 庫將它的 API 都放在了 window.$ 下,在載入完 jQuery 後,其他模組再通過 window.$ 去使用 jQuery。這樣做有很多問題,其中包括:    1、命名空間衝突,兩個庫可能會使用同一個名稱,例如 Zepto(http://zepto.com) 也是放在 window.$ 下  2、無法合理地管理項目的依賴和版本  3、無法方便地控制依賴的載入順序    當項目變大,這種方式將變得難以維護,需要用模組化的思想來組織程式碼。    模組化的特點:    1、提升開發效率:程式碼方便重用,別人開發的模組直接拿過來就可以使用,不需要重複開發法類似的功能。  2、方便後期維護:程式碼方便重用,別人開發的模組直接拿過來就可以使用,不需要重複開發法類似的功能。    模組化的規範:     伺服器端規範主要是CommonJS,node.js用的就是CommonJS規範。     客戶端規範主要有:AMD(非同步模組定義,推崇依賴前置)、CMD(通用模組定義,推崇依賴就近)。AMD規範的實現主要有RequireJS,CMD規範的主要實現有SeaJS。但是SeaJS已經停止維護了,因為在ES6中已經有了模組化的實現,隨著ES6的普及,第三方的模組化實現將會慢慢的淘汰。    本文主要介紹的也是CommonJS和ES6,所以其他的規範請允許我無恥的忽略了,下面進入正題:    一、CommonJS模組規範  CommonJS的核心思想是通過require方法來同步載入依賴的其他模組,通過module.exports到處需要暴露的介面。根據這個規範,每個文件就是一個模組,有自己的作用域。在一個文件裡面定義的變數、函數、類,都是私有的,對其他文件不可見。    module.exports:    // utils.js  let appid = '123456'  let bar = function (id) {      return `編號:${id}`  }  // 通過module.exports將appid與bar暴露出去  module.exports = {      appid , bar  }    ----------------------------------------------------     let utils = require('./utils') // 通過require引入utils   console.log(utils.appid) // 12345   console.log(utils.bar(2)) // 編號:2  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  exports:    為了方便,Node為每個模組提供一個exports變數,指向module.exports。這等同在每個模組頭部,有一行這樣的命令。    let exports = module.exports;    !!! 這裡要注意:    不能直接將exports變數指向一個值,因為這樣等於切斷了exports與module.exports的聯繫。    let exports = module.exports  let appid = '123456'  // 錯誤寫法  exports = {      appid  }  // 正確寫法  exports.appid = appid  1  2  3  4  5  6  7  8  二、ES6模組規範  不同於CommonJS,ES6使用 export 和 import 來導出、導入模組。    export:    // utils.js  export const appid = '123234'  export function getAppid() {    return '123456'  }    -------------------------------------------------  // 導出的幾種方式:  import { appid , getAppid } from './utils' // 導入多個導出  import * as utils from 'utils' // 作為命名空間導入整個模組  console.log(appid) // 123234  console.log(getAppid ()) // 123456  1  2  3  4  5  6  7  8  9  10  11  12  export default:    使用export default命令,為模組指定默認輸出,這裡要注意錯誤的一種寫法:    // 錯誤寫法  export default const appid = '123456'  // 正確寫法  const appid = '123456'  export default appid    ----------------------------------------------------    import utils from './utils' // 導入默認值  console.log(utils) // 123456  1  2  3  4  5  6  7  8  9  10  順便介紹一下import常用的幾種寫法:    import { foo, bar } from 『./utils』 // 導入多個導出  import * as utils from 『utils』 // 作為命名空間導入整個模組  import utils from 『utils』 // 導入默認值  import utils , { foo , bar } from 『./utils』 // 導入多個導出與默認導出  import { foo , bar } , * as utils from 『utils』 // 導入命名空間整個模組與多個導出  import(』./utils』).then (res) => { // do something} // import動態導入函數,當使用它的時候,會返回一個promise。  let module = await import(』./utils』) // 支援await關鍵字    三、相關文檔  CommonJS規範,http://javascript.ruanyifeng.com/nodejs/module.html  ES6 Module 的語法,http://es6.ruanyifeng.com/#docs/module  Import用法介紹,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import    本月開始學習小程式,會總結小程式專欄文章

Tags: