exports、module.exports 和 export、export default 到底是咋回事

城南發表於2017-07-31

前言

難得有空,今天開始重新規範的學習一下node程式設計。
但是引入模組我看到用 require的方式,再聯想到我們們的ES6各種exportexport default

阿西吧,頭都大了....

頭大完了,那我們坐下先理理他們的使用範圍。

require: node 和 es6 都支援的引入
export / import : 只有es6 支援的匯出引入
module.exports / exports: 只有 node 支援的匯出

這一刻起,我覺得是時候要把它們之間的關係都給捋清楚了,不然我得混亂死。話不多少,我們們開幹!!

node模組

Node裡面的模組系統遵循的是CommonJS規範。
那問題又來了,什麼是CommonJS規範呢?
由於js以前比較混亂,各寫各的程式碼,沒有一個模組的概念,而這個規範出來其實就是對模組的一個定義。

CommonJS定義的模組分為: 模組標識(module)、模組定義(exports) 、模組引用(require)

先解釋 exportsmodule.exports
在一個node執行一個檔案時,會給這個檔案內生成一個 exportsmodule物件,
module又有一個exports屬性。他們之間的關係如下圖,都指向一塊{}記憶體區域。

exports = module.exports = {};複製程式碼

記憶體結構示意圖
記憶體結構示意圖

那下面我們來看看程式碼的吧。

//utils.js
let a = 100;

console.log(module.exports); //能列印出結果為:{}
console.log(exports); //能列印出結果為:{}

exports.a = 200; //這裡辛苦勞作幫 module.exports 的內容給改成 {a : 200}

exports = '指向其他記憶體區'; //這裡把exports的指向指走

//test.js

var a = require('/utils');
console.log(a) // 列印為 {a : 200}複製程式碼

從上面可以看出,其實require匯出的內容是module.exports的指向的記憶體塊內容,並不是exports的。
簡而言之,區分他們之間的區別就是 exports 只是 module.exports的引用,輔助後者新增內容用的。

用白話講就是,exports只輔助module.exports操作記憶體中的資料,辛辛苦苦各種運算元據完,累得要死,結果到最後真正被require出去的內容還是module.exports的,真是好苦逼啊。

其實大家用記憶體塊的概念去理解,就會很清楚了。

然後呢,為了避免糊塗,儘量都用 module.exports 匯出,然後用require匯入。

ES中的模組匯出匯入

說實話,在es中的模組,就非常清晰了。不過也有一些細節的東西需要搞清楚。
比如 exportexport default,還有 匯入的時候,import a from ..,import {a} from ..,總之也有點亂,那麼下面我們就開始把它們捋清楚吧。

export 和 export default

首先我們講這兩個匯出,下面我們講講它們的區別

  1. export與export default均可用於匯出常量、函式、檔案、模組等
  2. 在一個檔案或模組中,export、import可以有多個,export default僅有一個
  3. 通過export方式匯出,在匯入時要加{ },export default則不需要
  4. export能直接匯出變數表示式,export default不行。

下面我們們看看程式碼去驗證一下

testEs6Export.js

'use strict'
//匯出變數
export const a = '100';  

 //匯出方法
export const dogSay = function(){ 
    console.log('wang wang');
}

 //匯出方法第二種
function catSay(){
   console.log('miao miao'); 
}
export { catSay };

//export default匯出
const m = 100;
export default m; 
//export defult const m = 100;// 這裡不能寫這種格式。複製程式碼

index.js

//index.js
'use strict'
var express = require('express');
var router = express.Router();

import { dogSay, catSay } from './testEs6Export'; //匯出了 export 方法 
import m from './testEs6Export';  //匯出了 export default 

import * as testModule from './testEs6Export';//as 集合成物件匯出



/* GET home page. */
router.get('/', function(req, res, next) {
  dogSay();
  catSay();
  console.log(m);
  testModule.dogSay();
  console.log(testModule.m); // undefined , 因為  as 匯出是 把 零散的 export 聚集在一起作為一個物件,而export default 是匯出為 default屬性。
  console.log(testModule.default); // 100
  res.send('恭喜你,成功驗證');
});

module.exports = router;複製程式碼

從上面可以看出,確實感覺 ES6的模組系統非常靈活的。

程式碼地址

GitHub: github.com/XuXiaoGH/ex…

參考文獻

1.老樹新芽,在ES6下使用Express
2.exports 和 module.exports 的區別
3.module.exports與exports,export與export default之間的關係

感謝這三位前輩的分享。

寫在最後

如果文章對你有所幫助,不妨點個喜歡,這將是支援我繼續寫下去的動力。

謝謝親們。

最後再感謝3樓的humor老哥指出錯誤。

相關文章