摘要:模塊載入策略的模塊分為兩類,一類為原生核心模塊,一類為文件模塊。最后傳入對象的,方法,,文件名,目錄名作為實(shí)參并執(zhí)行。在這個(gè)主文件中,可以通過方法去引入其余的模塊。以上所描述的模塊載入機(jī)制均定義在中。
CommonJS規(guī)范?
早在Netscape誕生不久后,JavaScript就一直在探索本地編程的路,Rhino是其代表產(chǎn)物。無奈那時(shí)服務(wù)端JavaScript走的路均是參考眾多服務(wù)器端語言來實(shí)現(xiàn)的,在這樣的背景之下,一沒有特色,二沒有實(shí)用價(jià)值。但是隨著JavaScript在前端的應(yīng)用越來越廣泛,以及服務(wù)端JavaScript的推動,JavaScript現(xiàn)有的規(guī)范十分薄弱,不利于JavaScript大規(guī)模的應(yīng)用。那些以JavaScript為宿主語言的環(huán)境中,只有本身的基礎(chǔ)原生對象和類型,更多的對象和API都取決于宿主的提供,所以,我們可以看到JavaScript缺少這些功能:
JavaScript沒有模塊系統(tǒng)。沒有原生的支持密閉作用域或依賴管理。?
JavaScript沒有標(biāo)準(zhǔn)庫。除了一些核心庫外,沒有文件系統(tǒng)的API,沒有IO流API等。?
JavaScript沒有標(biāo)準(zhǔn)接口。沒有如Web Server或者數(shù)據(jù)庫的統(tǒng)一接口。?
JavaScript沒有包管理系統(tǒng)。不能自動加載和安裝依賴。?
于是便有了CommonJS(http://www.commonjs.org)規(guī)范的出現(xiàn),其目標(biāo)是為了構(gòu)建JavaScript在包括Web服務(wù)器,桌面,命令行工具,及瀏覽器方面的生態(tài)系統(tǒng)。CommonJS制定了解決這些問題的一些規(guī)范,而Node.js就是這些規(guī)范的一種實(shí)現(xiàn)。Node.js自身實(shí)現(xiàn)了require方法作為其引入模塊的方法,同時(shí)NPM也基于CommonJS定義的包規(guī)范,實(shí)現(xiàn)了依賴管理和模塊自動安裝等功能。這里我們將深入一下Node.js的require機(jī)制和NPM基于包規(guī)范的應(yīng)用。
簡單模塊定義和使用
在Node.js中,定義一個(gè)模塊十分方便。我們以計(jì)算圓形的面積和周長兩個(gè)方法為例,來表現(xiàn)Node.js中模塊的定義方式。
1 var PI = Math.PI; 2 exports.area = function (r) { 3 return PI * r * r; 4 }; 5 exports.circumference = function (r) { 6 return 2 * PI * r; 7 };}//歡迎加入全棧開發(fā)交流圈一起學(xué)習(xí)交流:582735936 ]//面向1-3年前端人員 } //幫助突破技術(shù)瓶頸,提升思維能力
將這個(gè)文件存為circle.js,并新建一個(gè)app.js文件,并寫入以下代碼:
1 var circle = require("./circle.js"); 2 console.log( "The area of a circle of radius 3 is " + circle.area( 4));
可以看到模塊調(diào)用也十分方便,只需要require需要調(diào)用的文件即可。
在require了這個(gè)文件之后,定義在exports對象上的方法便可以隨意調(diào)用。Node.js將模塊的定義和調(diào)用都封裝得極其簡單方便,從API對用戶友好這一個(gè)角度來說,Node.js的模塊機(jī)制是非常優(yōu)秀的。
模塊載入策略
Node.js的模塊分為兩類,一類為原生(核心)模塊,一類為文件模塊。原生模塊在Node.js源代碼編譯的時(shí)候編譯進(jìn)了二進(jìn)制執(zhí)行文件,加載的速度最快。另一類文件模塊是動態(tài)加載的,加載速度比原生模塊慢。但是Node.js對原生模塊和文件模塊都進(jìn)行了緩存,于是在第二次require時(shí),是不會有重復(fù)開銷的。其中原生模塊都被定義在lib這個(gè)目錄下面,文件模塊則不定性。
node app.js
由于通過命令行加載啟動的文件幾乎都為文件模塊。我們從Node.js如何加載文件模塊開始談起。加載文件模塊的工作,主要由原生模塊module來實(shí)現(xiàn)和完成,該原生模塊在啟動時(shí)已經(jīng)被加載,進(jìn)程直接調(diào)用到runMain靜態(tài)方法。
1 // bootstrap main module. 2 Module.runMain = function () { 3 // Load the main module--the command line argument. 4 Module._load(process.argv[1], null, true); 5 };
_load靜態(tài)方法在分析文件名之后執(zhí)行
var module = new Module(id, parent);
并根據(jù)文件路徑緩存當(dāng)前模塊對象,該模塊實(shí)例對象則根據(jù)文件名加載。
module.load(filename);
實(shí)際上在文件模塊中,又分為3類模塊。這三類文件模塊以后綴來區(qū)分,Node.js會根據(jù)后綴名來決定加載方法。
.js。通過fs模塊同步讀取js文件并編譯執(zhí)行。?
.node。通過C/C++進(jìn)行編寫的Addon。通過dlopen方法進(jìn)行加載。?
.json。讀取文件,調(diào)用JSON.parse解析加載。
這里我們將詳細(xì)描述js后綴的編譯過程。Node.js在編譯js文件的過程中實(shí)際完成的步驟有對js文件內(nèi)容進(jìn)行頭尾包裝。
以app.js為例,包裝之后的app.js將會變成以下形式:
1 (function (exports, require, module, __filename, __dirname) { 2 var circle = require("./circle.js"); 3 console.log("The area of a circle of radius 4 is " + circle.area(4)); 4 });
這段代碼會通過vm原生模塊的runInThisContext方法執(zhí)行(類似eval,只是具有明確上下文,不污染全局),返回為一個(gè)具體的function對象。最后傳入module對象的exports,require方法,module,文件名,目錄名作為實(shí)參并執(zhí)行。
這就是為什么require并沒有定義在app.js 文件中,但是這個(gè)方法卻存在的原因。從Node.js的API文檔中可以看到還有__filename、__dirname、module、exports幾個(gè)沒有定義但是卻存在的變量。其中__filename和__dirname在查找文件路徑的過程中分析得到后傳入的。module變量是這個(gè)模塊對象自身,exports是在module的構(gòu)造函數(shù)中初始化的一個(gè)空對象({},而不是null)。
在這個(gè)主文件中,可以通過require方法去引入其余的模塊。而其實(shí)這個(gè)require方法實(shí)際調(diào)用的就是load方法。
load方法在載入、編譯、緩存了module后,返回module的exports對象。這就是circle.js文件中只有定義在exports對象上的方法才能被外部調(diào)用的原因。
以上所描述的模塊載入機(jī)制均定義在lib/module.js中。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/40226.html
摘要:模塊載入策略的模塊分為兩類,一類為原生核心模塊,一類為文件模塊。最后傳入對象的,方法,,文件名,目錄名作為實(shí)參并執(zhí)行。在這個(gè)主文件中,可以通過方法去引入其余的模塊。以上所描述的模塊載入機(jī)制均定義在中。 CommonJS規(guī)范? 早在Netscape誕生不久后,JavaScript就一直在探索本地編程的路,Rhino是其代表產(chǎn)物。無奈那時(shí)服務(wù)端JavaScript走的路均是參考眾多服務(wù)器端...
摘要:是一個(gè)針對網(wǎng)絡(luò)應(yīng)用開發(fā)的平臺它基于的運(yùn)行時(shí)引擎但它不僅僅只是的標(biāo)準(zhǔn)類庫是它非常重要的一部分它涵蓋了從服務(wù)端到同步或者異步的文件管理已經(jīng)迅速成為一個(gè)可行并且真正高效的開發(fā)平臺在誕生之前在服務(wù)端運(yùn)行是件不可思議的事情并且對其他腳本語言來說要實(shí)現(xiàn) Node是一個(gè)針對網(wǎng)絡(luò)應(yīng)用開發(fā)的平臺,它基于Google的JavaScript運(yùn)行時(shí)引擎V8,但它不僅僅只是V8.Node的標(biāo)準(zhǔn)類庫是它非常重要的...
摘要:最近利用空閑時(shí)間寫了一個(gè)從入門到上線的的實(shí)戰(zhàn)教程從入門到上線目前還在更新中,入門篇已基本成型。本項(xiàng)目使用語法,采用搭建了一個(gè)博客系統(tǒng),實(shí)現(xiàn)了文章管理用戶登錄注冊權(quán)限控制分類管理等功能。實(shí)現(xiàn)線上部署左手代碼右手磚拋磚引玉 最近利用空閑時(shí)間寫了一個(gè)從入門到上線的的node實(shí)戰(zhàn)教程《Node.js從入門到上線》A blog build with Koa2. 目前還在更新中,入門篇已基本成型。...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡介現(xiàn)在,越來越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說明 2017-12-14 我發(fā)了一篇文章《沒用過Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車的還坐過站了。大家可以很...
閱讀 824·2021-09-07 09:58
閱讀 2682·2021-08-31 09:42
閱讀 2855·2019-08-30 14:18
閱讀 3086·2019-08-30 14:08
閱讀 1831·2019-08-30 12:57
閱讀 2759·2019-08-26 13:31
閱讀 1299·2019-08-26 11:58
閱讀 1052·2019-08-23 18:06