node 學習筆記 - Modules 模塊加載系統 (2)


本文同步自我的個人博客:http://www.52cik.com/2015/12/14/learn-node-modules-module.html

上一篇講了模塊是如何被尋找到然后加載進來的,這篇則是如何導出屬性方法以及自定義模塊后綴等一系列模塊問題。

exports 對象

這是最常見的對象了,以往導出都是這樣寫的。

// a.js
exports.bar = '屬性';
exports.fn = function () { return '方法' };

// b.js
var a = require('./a');
console.log(a.bar); // 屬性
console.log(a.fn()); // 方法

一直都是這么用非常簡單,但是不能直接用對象覆蓋他,如下代碼是不對的。

// a.js
exports = {
  bar: '屬性',
  fn: function () { return '方法' }
};

// b.js
var a = require('./a');
console.log(a.bar); // undefined
console.log(a.fn()); // 報錯

為什么不能直接覆蓋呢,因為 exports 只是 module.exports 對象的引用。

module.exports 對象

如果要導出一整個對象或者構造函數之類的,就需要用到 module.exports 對象了。

// a.js
module.exports = {
  bar: '屬性',
  fn: function () { return '方法' }
};

// b.js
var a = require('./a');
console.log(a.bar); // 屬性
console.log(a.fn()); // 方法

導出構造函數:

// klass.js
function klass () {}
klass.prototype.say = function () { return '我是klass' };
module.exports = klass;

// b.js
var Klass = require('./klass');
var klass = new Klass();
console.log(klass.say()); // 我是klass

module 其他屬性

module 還有些其他屬性,簡單說下吧。

  • module.id 模塊id,往往是模塊路徑
  • module.children 子模塊
  • module.filename 模塊路徑
  • module.loaded 是否加載完畢
  • module.parent 父模塊
  • module.paths 各級 node_modules 目錄路徑

require 函數

說模塊,當然離不開 require 函數,除了加載模塊之外,他還有一些其他用法。

  • require.resolve 不會加載執行,只會返回模塊的絕對路徑。
  • require.cache 緩存所有已經加載的模塊,如果你要更新模塊就要刪除這里的緩存。
var a = require('./a');
var p = require.resolve('./a'); // 得到模塊路徑

delete require.cache[p]; // 刪除模塊緩存

雖然不清楚什么時候用,但是至少是這么用的,刪除緩存后,下次加載這個模塊,就會重新加載模塊文件了。

require.extensions 自定義模塊后綴

還有個 require.extensions 非常好用的屬性,但遺憾的是官方提示棄用了這個屬性,不過值得慶幸的是,這個屬性永遠不會被移除,只是不推薦使用而已。

我第一次注意到這個屬性是在 ejs 源碼里,當時很好奇這是個什么東西,去翻了下官方文檔,發現撿到寶了。后來又發現 node 命令行下的 babel 模塊也注冊了自定義模塊,后綴分別是 .es, .es6, .jsx,可以直接 require('./a.es6') 或者是 require('./a.jsx') 得到編譯好的 js 代碼。

好了,不說廢話了,來看個官方簡單例子吧。

require.extensions['.json'] = function(module, filename) {
  var content = fs.readFileSync(filename, 'utf8');
  try {
    module.exports = JSON.parse(content);
  } catch (err) {
    err.message = filename + ': ' + err.message;
    throw err;
  }
};

這是 node 源碼的 json 模塊實現,我只是刪除了一個 stripBOM 函數,為了方便大家理解。

當然官方不推薦這樣做是有道理的,官方推薦編譯為兼容的 js 代碼模塊運行,性能更佳,而不應該采用這樣的自定義模塊實現。
不過看用途而定了,有時候也不一定追求極致的性能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM