理解nodejs的module

秋雨發表於2019-02-16

module

在 Node.js 模組系統中,每個檔案都視為獨立的模組,node在執行某個模組兒時會生成一個module物件

Module {
  id: `.`,
  exports: 2,
  parent: null,
  filename: `/Users/leinov/github/node-api/module/module.js`,
  loaded: false,
  children:
   [ Module {
       id: `/Users/leinov/github/node-api/module/circle.js`,
       exports: [Object],
       parent: [Circular],
       filename: `/Users/leinov/github/node-api/module/circle.js`,
       loaded: true,
       children: [],
       paths: [Array] } ],
  paths:
   [ `/Users/leinov/github/node-api/module/node_modules`,
     `/Users/leinov/github/node-api/node_modules`,
     `/Users/leinov/github/node_modules`,
     `/Users/leinov/node_modules`,
     `/Users/node_modules`,
     `/node_modules` ] }
  • id為當前檔案
  • exports為當前node檔案模組兒匯出的值
  • parent為父級呼叫,如果為null則該檔案沒有被呼叫
  • filename為當前檔名
  • loaded是否被載入
  • children 引入模組陣列,陣列項格式同module
  • paths為node模組兒 node_modules 模組兒查詢路徑,一直查到根目錄

module.exports & exports

Node裡面的模組系統遵循是CommonJs規範,CommonJs定義的模組分為: 模組標識(module)、模組定義(exports) 、模組引用(require),在模組兒執行的時候都會生成一個module物件和一個exports物件,module物件下也有一個exports物件,預設情況下這兩個物件都是空物件。如果有引用其他模組兒或定義模組兒 即module.exports或者exports被賦值時,則該模組兒就是一個有效的帶有返回值的模組兒。

一個模組兒真正匯出的是module.exports的值,exports只是module.exports的一個引用
可以簡單理解為下面這種物件引用和賦值的區別

let obj1 = {a=1};
let obj2 = obj1;

console.log(obj1,obj2); // {a:1} {a:1}

obj2.a = 2 
console.log(obj1,obj2); // {a:2} {a:2}

obj2 = {b:3} 

console.log(obj1,obj2); // {a:2} {b:3}

obj2只是obj1的一個引用。當 obj2.a 改變時其實改變的是 obj1obj2 都指向的同一個堆裡的資料。但 obj2 ={b:3} 則重新在堆裡開闢了另一個記憶體塊兒來儲存。已經跟 obj1 脫離沒有關係了

所以經常會看到node模組兒裡會像下面這樣來匯出模組兒。

exports = module.exports = ()=>{
    do something
}

這是為了讓exports引用指向module.exports同一塊記憶體,確保資料的一致性。

總結

  • 在執行 node 檔案時同事建立了 module.exportsexports 物件
  • exports 是指向 module.exports 的一個引用
  • require("xxx") 其實引用的是xxx中的 module.exports 而非 exports

github nodejs

相關文章