摘要:本文轉發自本人。這個例子通過對進行計算,即通過函數處理該字符串腳本。實現的功能與函數類似,但比函數更強大。返回模塊中暴露的接口以供調用。但如果給重新賦值,則會失去的引用此時,意味著通過暴露的接口是無效的,沒有添加到中的中。
Node.js design pattern一書中對Node的Module模塊機制這一塊,我覺得講的挺透徹和易懂,這里根據自己理解做下總結。本文轉發自本人github。
loadModule自定義一個簡單的模塊加載方法loadModule,基本思路跟nodejs一致,將加載的模塊內容包裹在一個函數里面實現變量的隔離,保證模塊內的變量都是私有的。
function loadModule(filename, module, require) { const wrappedSrc = `(function(module, exports, require) { ${fs.readFileSync(filename, "utf8")} })(module, module.exports, require);`; eval(wrappedSrc); }
這個例子通過eval對wrappedSrc進行計算,即通過eval函數處理該字符串腳本。因為這里要把(function(module, exports, require) { 這串東西和 fs.readFileSync(filename, "utf8")加載的模塊內容合并在一起作為新的整合代碼再運行,所以必須借助eval函數。
作為對比,在nodejs源碼中, wrap是這樣實現的
Module.wrap = function(script) { return Module.wrapper[0] + script + Module.wrapper[1]; }; Module.wrapper = [ "(function (exports, require, module, __filename, __dirname) { ", " });" ];
最終對該warpper的解析實現在Module.prototype._compile方法中,其中用到了vm模塊對wrapper腳本進行處理。vm實現的功能與eval函數類似,但比eval函數更強大。
模塊引用require()對模塊的引用我們通過require(..)函數進行引用,如var http = require("http"),該方法簡單實現如下:
const require = (moduleName) => { console.log(`Require invoked for module: ${moduleName}`); const id = require.resolve(moduleName); if (require.cache[id]) { return require.cache[id].exports; } // 1.module metadata const module = { exports: {}, id: id } // 2.require.cache require.cache[id] = module; // 3.load the module loadModule(id, module, require); // 4.return exported variables return module.exports; } require.cache = {}; require.resolve = (moduleName) => { /* resolve a full module id from the moduleName */ }
定義了一個module對象用來保存通過loadModule方法中加載模塊中暴露出的接口。
將第一次加載的模塊保存在內部緩存中。即第二次調用require(..)時不會再調用loadModule方法,直接從cache中返回。
通過loadModule方法通過模塊路徑加載模塊內容。
返回模塊中暴露的接口以供調用。
可以通過下圖更加直觀的了解其中的關系。
module.exports vs exports
通過上述代碼和圖示可知,我們寫的模塊中的exports其實是對module.exports的引用。 因此我們可以通過exports添加屬性來給module.exports引用的對象添加屬性。
exports.hello = () => { console.log("Hello") };
但如果給exports重新賦值,則會失去module.exports的引用
exports = () => { console.log("Hello") };
此時exports !== module.exports,意味著通過exports暴露的接口是無效的,沒有添加到module metadata中的exports中。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92473.html
摘要:現在,我們可以開始探討介面的設計模式了。匯出命名空間一個簡單且常用的設計模式就是匯出一個包含數個屬性的物件,這些屬性具體的內容主要是函式,但並不限於函式。如此,我們就能夠透過匯入該模組來取得這個命名空間下一系列相關的功能。 前言 這篇文章試著要整理,翻譯Export This: Interface Design Patterns for Node.js Modules這篇非常值得一讀的...
摘要:前端日報精選譯用搭建探索生命周期中的匿名遞歸瀏覽器端機器智能框架深入理解筆記和屬性中文上海線下活動前端工程化架構實踐滬江技術沙龍掘金周二放送追加視頻知乎專欄第期聊一聊前端自動化測試上雙關語來自前端的小段子,你看得懂嗎眾成翻 2017-08-10 前端日報 精選 [譯] 用 Node.js 搭建 API Gateway探索 Service Worker 「生命周期」JavaScript ...
摘要:此處的構造函數使用的形式添加新屬性,但實際上新屬性的添加有四種方式,除去這一種,還有三種方括號語法,方法方法此處舉的是原文中的例子,若要使用,可參考原文。 參考書籍Learning Javascript Design Patterns 一、設計模式概述與應用場景 首先引用原書的一段話: Patterns are proven solutions: They provide solid ...
摘要:前端日報精選讀書思考一的計算屬性使用開發調試開發者控制臺中,你可能意想不到的功能中字符串轉數字的陷阱和示例中文設計模式單例模式個人文章設計模式工廠模式個人文章讀書思考二掘金網絡基礎三傳輸層的筆記學習筆記中的屬性學習 2017-10-08 前端日報 精選 Node.js Design Patterns - Second Edition讀書思考(一)Vue的計算屬性_Vue使用typesc...
摘要:為何會有這個自學也需要有章可尋,早上整理了一下這段時間學的內容東西比較多,接下來的一段時間都會圍繞這個展開學習,當然這張前端自學圖譜并不是一成不變的,隨著時間的推移我會調整這張里的內容,總的目標只有一個系統化的學好前端的技術,我會隨時調整完 為何會有這個Roadmap 自學也需要有章可尋,早上整理了一下這段時間學的內容東西比較多,接下來的一段時間都會圍繞這個Roadmap展開學習,當然...
閱讀 1412·2023-04-26 01:58
閱讀 2289·2021-11-04 16:04
閱讀 1776·2021-08-31 09:42
閱讀 1768·2021-07-25 21:37
閱讀 1069·2019-08-30 15:54
閱讀 2078·2019-08-30 15:53
閱讀 3055·2019-08-29 13:28
閱讀 2693·2019-08-29 10:56