(轉)Node.js module.exports與exports

本文轉自Node.js module.exports與exports
做者: chemdemojavascript

折騰Node.js有些日子了,下面將陸陸續續記錄下使用Node.js的一些細節。java

熟悉Node.js的童鞋都知道,Node.js做爲服務器端的javascript運行環境,它使用npm做爲通用的包管理工具,npm遵循CommonJS規範定義了一套用於Node.js模塊的約定,關於npm實現Node.js模塊的更多細節請細讀深刻Node.js的模塊機制,這裏簡單講下書寫Node.js代碼時module.exports與exorts的區別。git

在瀏覽器端js裏面,爲了解決各模塊變量衝突等問題,每每藉助於js的閉包把全部模塊相關的代碼都包裝在一個匿名函數裏。而Node.js編寫模塊至關的自由,開發者只須要關注require,exports,module等幾個變量就足夠,而爲了保持模塊的可讀性,很推薦把不一樣功能的代碼塊都寫成獨立模塊,減小各模塊耦合。開發者能夠在「全局」環境下任意使用var申明變量(不用寫到閉包裏了),經過exports暴露接口給調用者。github

咱們常常看到相似export.xxx = yyy或者module.exports = xx這樣的代碼,可實際在經過require函數引入模塊時會出現報錯的狀況,這是什麼緣由致使的呢?npm

Node.js在模塊編譯的過程當中會對模塊進行包裝,最終會返回相似下面的代碼:瀏覽器

(function (exports, require, module, __filename, __dirname) {
    // module code...
});

其中,module就是這個模塊自己,require是對Node.js實現查找模塊的模塊Module._load實例的引用,__filename和__dirname是Node.js在查找該模塊後找到的模塊名稱和模塊絕對路徑,這就是官方API裏頭這兩個全局變量的來歷。服務器

關於module.exports與exorts的區別,瞭解了下面幾點以後應該就徹底明白:閉包

模塊內部大概是這樣:函數

exports = module.exports = {};
  • exports是module.exports的一個引用
  • require引用模塊後,返回給調用者的是module.exports而不是exports
  • exports.xxx,至關於在導出對象上掛屬性,該屬性對調用模塊直接可見
  • exports =至關於給exports對象從新賦值,調用模塊不能訪問exports對象及其屬性
  • 若是此模塊是一個類,就應該直接賦值module.exports,這樣調用者就是一個類構造器,能夠直接new實例
    客官若是看明白咋回事兒了下面的內容能夠忽略:)

假若有模塊a.js代碼以下:工具

exports.str = 'a';
exports.fn = function() {};

對a模塊的調用:

var a = require('./a');
console.log(a.str);
console.log(a.fn());

這樣用是對的,若是改造a以下:

exports.str = 'a';
exports = function fn() {};

在調用a模塊時天然沒用fn屬性了。

再改造下a模塊:

exports.str = 'a';
module.exports = function fn() {};

這時a模塊其實就是fn函數的引用,也就是說能夠require('./a')()這樣使用,而同時再也不有str屬性了。

下面直接導出一個類:

module.exports = function A() {};

調用:

var A = require('./a');
var a = new A();

總結下,有兩點:

  1. 對於要導出的屬性,能夠簡單直接掛到exports對象上
  2. 對於類,爲了直接使導出的內容做爲類的構造器可讓調用者使用new操做符建立實例對象,應該把構造函數掛到module.exports對象上,不要和導出屬性值混在一塊兒 最後,不用再糾結module.exports與exorts何時該用哪一個了吧~
相關文章
相關標籤/搜索