module.exports、exports、export、export default之間的關係和區別
對於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 本月開始學習小程式,會總結小程式專欄文章