欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Node中模塊實(shí)現(xiàn)過(guò)程是怎么樣的

今天就跟大家聊聊有關(guān)Node中模塊實(shí)現(xiàn)過(guò)程是怎么樣的,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

站在用戶(hù)的角度思考問(wèn)題,與客戶(hù)深入溝通,找到峨眉山網(wǎng)站設(shè)計(jì)與峨眉山網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶(hù)體驗(yàn)好的作品,建站類(lèi)型包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋峨眉山地區(qū)。

CommonJS 定義了 module、exports 和 require 模塊規(guī)范,Node.js 為了實(shí)現(xiàn)這個(gè)簡(jiǎn)單的標(biāo)準(zhǔn),從底層 C/C++ 內(nèi)建模塊到 JavaScript 核心模塊,從路徑分析、文件定位到編譯執(zhí)行,經(jīng)歷了一系列復(fù)雜的過(guò)程。簡(jiǎn)單的了解 Node 模塊的原理,有利于我們重新認(rèn)識(shí)基于 Node 搭建的框架。

一、CommonJS 模塊規(guī)范

CommonJS 規(guī)范或標(biāo)準(zhǔn)簡(jiǎn)單來(lái)說(shuō)是一種理論,它期望 JavaScript 可以具備跨宿主環(huán)境執(zhí)行的能力,不僅可以開(kāi)發(fā)客戶(hù)端應(yīng)用,還可以開(kāi)發(fā)服務(wù)端應(yīng)用、命令行工具、桌面圖形界面應(yīng)用等。

CommonJS 規(guī)范對(duì)模塊的定義分為三個(gè)部分:

模塊定義

在模塊中存在module對(duì)象代表模塊本身,模塊上下文提供exports屬性 ,將方法掛載在exports對(duì)象上即可以定義導(dǎo)出方式,例如:

    // math.js
   exports.add = function(){ //...}

模塊引用

module提供require()方法引入外部模塊的 API 到當(dāng)前的上下文中:

   var math = require('math')

模塊標(biāo)識(shí)

模塊標(biāo)識(shí)實(shí)際就是傳遞給require()方法中的參數(shù),可以是按小駝峰(camelCase)命名的字符串,也可以是文件路徑。

Node.js 借鑒了 CommonJS 規(guī)范的設(shè)計(jì),特別是 CommonJS 的 Modules 規(guī)范,實(shí)現(xiàn)了一套模塊系統(tǒng),同時(shí) NPM 實(shí)現(xiàn)了 CommonJS 的 Packages 規(guī)范,模塊和包組成了 Node 應(yīng)用開(kāi)發(fā)的基礎(chǔ)。

二、Node 模塊加載原理

上述模塊規(guī)范看起來(lái)十分簡(jiǎn)單,只有module、exports和require,但 Node 是如何實(shí)現(xiàn)的呢?

需要經(jīng)歷路徑分析(模塊的完整路徑)、文件定位(文件擴(kuò)展名或目錄)、編譯執(zhí)行三個(gè)步驟。

2.1 路徑分析

回顧require()接收 模塊標(biāo)識(shí) 作為參數(shù)來(lái)引入模塊,Node 就是基于這個(gè)標(biāo)識(shí)符進(jìn)行路徑分析。不同的標(biāo)識(shí)符采用的分析方式是不同的,主要分為一下幾類(lèi):

Node 提供的核心模塊,如 http、fs、path

核心模塊在 Node 源碼編譯時(shí)存為二進(jìn)制執(zhí)行文件,在 Node 啟動(dòng)時(shí)直接加載到內(nèi)存中,路徑分析中優(yōu)先判斷,所以加載速度很快,而且也不用后續(xù)的文件定位和編譯執(zhí)行。

如果想加載與核心模塊同名的自定義模塊,如自定義 http 模塊,那必須選用不同標(biāo)志符或改用路徑方式。

路徑形式的文件模塊,.、..相對(duì)路徑模塊和/絕對(duì)路徑模塊

以.、..或/開(kāi)始的標(biāo)識(shí)符都會(huì)當(dāng)成文件模塊處理,Node 會(huì)將require()中的路徑轉(zhuǎn)為真實(shí)路徑作為索引,然后編譯執(zhí)行。

由于文件模塊明確了文件位置,所以縮短了路徑分析時(shí)間,加載速度僅慢與核心模塊。

自定義模塊,即非路徑形式的文件模塊

即不是核心模塊,也不是路徑形式的文件模塊,自定義文件是特殊的文件模塊,在路徑查找時(shí) Node 會(huì)逐級(jí)查找該模塊路徑中的路徑。  
模塊路徑查找策略示例如下:

// paths.js
console.log(module.paths)

// Terminal
$ node paths.js
[ '/Users/tong/WebstormProjects/testNode/node_modules',
'/Users/tong/WebstormProjects/node_modules',
'/Users/tong/node_modules',
'/Users/node_modules',
'/node_modules' ]

從上述示例輸出的模塊路徑數(shù)組可以看出,模塊的查找時(shí)沿當(dāng)前路徑向上逐級(jí)查找node_modules目錄,直到目標(biāo)路徑為止,類(lèi)似 JS 原型鏈或作用域鏈。路徑越深速度越慢,所以自定義模塊加載速度最慢。

緩存優(yōu)先機(jī)制:Node 會(huì)對(duì)引入過(guò)的模塊進(jìn)行緩存以提高性能,不同于瀏覽器緩存的是文件,Node 緩存的是編譯和執(zhí)行后的對(duì)象,所以require()對(duì)相同模塊的二次加載采用緩存優(yōu)先的方式。這個(gè)緩存優(yōu)先是第一優(yōu)先級(jí)的,比核心模塊的優(yōu)先級(jí)要高!

2.2 文件定位

模塊路徑分析完成后是文件定位,主要包括文件擴(kuò)展名的分析、目錄和包的處理。為了表達(dá)的更清晰,將文件定位分為四個(gè)步驟:

step1: 補(bǔ)充擴(kuò)展名

通常require()中的標(biāo)識(shí)符是不包含文件擴(kuò)展名的,這種情況下,Node會(huì)按照 .js、.json、.node 的順序嘗試補(bǔ)充擴(kuò)展名。

在嘗試補(bǔ)充擴(kuò)展名時(shí),需要調(diào)用 fs 模塊同步阻塞式判斷文件是否存在,所以這里提升性能的小技巧,就是 .json 和 .node 文件傳遞給require()時(shí)帶上擴(kuò)展名會(huì)加快一些速度。

step2: 目錄處理查找 pakage.json

如果補(bǔ)充擴(kuò)展名后沒(méi)有找到對(duì)應(yīng)文件,但是得到了一個(gè)目錄,此時(shí) Node會(huì)將目錄當(dāng)做一個(gè)包處理。依據(jù) CommonJS 包規(guī)范的實(shí)現(xiàn),Node 會(huì)在目錄下查找pakage.json(包描述文件),通過(guò)JSON.parse()解析成包描述對(duì)象,從中取main屬性指定的文件名定位。

step3: 繼續(xù)默認(rèn)查找 index 文件

如果沒(méi)有pakage.json或者main屬性指定的文件名錯(cuò)誤,那 Node 會(huì)將 index 當(dāng)做默認(rèn)文件名,依次查找 index.js、index.json、index.node

step4: 進(jìn)入下一個(gè)模塊路徑

在上述目錄分析過(guò)程中沒(méi)有成功定位時(shí),自定義模塊按路徑查找策略進(jìn)入上一層node_modules目錄,當(dāng)整個(gè)模塊路徑數(shù)組遍歷完畢后沒(méi)有定位到文件,則會(huì)拋出查找失敗異常。

緩存加載的優(yōu)化策略使得二次引入不需要路徑分析、文件定位、編譯執(zhí)行這些過(guò)程,而且核心模塊也不需要文件定位的過(guò)程,這大大提高了再次加載模塊時(shí)的效率

2.3 編譯執(zhí)行

Node 中每個(gè)模塊都是一個(gè)對(duì)象,在具體定位到文件后,Node 會(huì)新建該模塊對(duì)象,然后根據(jù)路徑載入并編譯。不同的文件擴(kuò)展名載入方法為:

.js 文件: 通過(guò) fs 模塊同步讀取后編譯執(zhí)行.json 文件: 通過(guò) fs 模塊同步讀取后,用JSON.parse()解析并返回結(jié)果.node 文件: 這是用 C/C++ 寫(xiě)的擴(kuò)展文件,通過(guò)process.dlopen()方法加載最后編譯生成的其他擴(kuò)展名: 都被當(dāng)做 js 文件載入

載入成功后 Node 會(huì)調(diào)用具體的編譯方式將文件執(zhí)行后返回給調(diào)用者。對(duì)于 .json 文件的編譯最簡(jiǎn)單,JSON.parse()解析得到對(duì)象后直接賦值給模塊對(duì)象的exports,而 .node 文件是C/C++編譯生成的,Node 直接調(diào)用process.dlopen()載入執(zhí)行就可以,下面重點(diǎn)介紹 .js 文件的編譯:

在 CommonJS 模塊規(guī)范中有module、exports 和 require 這3個(gè)變量,在 Node API 文檔中每個(gè)模塊還有 __filename、__dirname這兩個(gè)變量,但是在模塊中沒(méi)有定義這些變量,那它們是怎么產(chǎn)生的呢?

事實(shí)上在編譯過(guò)程中,Node 對(duì)每個(gè) JS 文件都被進(jìn)行了封裝,例如一個(gè) JS 文件會(huì)被封裝成如下:

(function (exports, require, module, __filename, __dirname) {
    var math = require('math')
    export.add = function(){ //... }
})

首先每個(gè)模塊文件之間都進(jìn)行了作用域隔離,通過(guò)vm原生模塊的runInThisContext()方法(類(lèi)似 eval)返回一個(gè)具體的 function 對(duì)象,最后將當(dāng)前模塊對(duì)象的exports屬性、require()方法、模塊對(duì)象本身module、文件定位時(shí)得到的完整路徑__filename和文件目錄__dirname作為參數(shù)傳遞給這個(gè) function 執(zhí)行。模塊的exports屬性上的任何方法和屬性都可以被外部調(diào)用,其余的則不可被調(diào)用。

至此,module、exports 和 require的流程就介紹完了。

曾經(jīng)困惑過(guò),每個(gè)模塊都可以使用exports的情況下,為什么還必須用module.exports。

這是因?yàn)閑xports在編譯過(guò)程中時(shí)通過(guò)形參傳入的,直接給exports形參賦值只改變形參的引用,不能改變作用域外的值,例如:

let change = function (exports) {
  exports = 100
  console.log(exports)
}

var exports = 2
change(exports) // 100
console.log(exports) // 2

所以直接賦值給module.exports對(duì)象就不會(huì)改變形參的引用了。

編譯成功的模塊會(huì)將文件路徑作為索引緩存在 Module._cache 對(duì)象上,路徑分析時(shí)優(yōu)先查找緩存,提高二次引入的性能。

三、Node 核心模塊

總結(jié)來(lái)說(shuō) Node 模塊分為Node提供的核心模塊和用戶(hù)編寫(xiě)的文件模塊。文件模塊是在運(yùn)行時(shí)動(dòng)態(tài)加載,包括了上述完整的路徑分析、文件定位、編譯執(zhí)行這些過(guò)程,核心模塊在Node源碼編譯成可執(zhí)行文件時(shí)存為二進(jìn)制文件,直接加載在內(nèi)存中,所以不用文件定位和編譯執(zhí)行。

核心模塊分為 C/C++ 編寫(xiě)的和 JavaScript 編寫(xiě)的兩部分,在編譯所有 C/C++ 文件之前,編譯程序需要將所有的 JavaScript 核心模塊編譯為 C/C++ 可執(zhí)行代碼,編譯成功的則放在 NativeModule._cache對(duì)象上,顯然和文件模塊 Module._cache的緩存位置不同。

在核心模塊中,有些模塊由純 C/C++ 編寫(xiě)的內(nèi)建模塊,主要提供 API 給 JavaScript 核心模塊,通常不能被用戶(hù)直接調(diào)用,而有些模塊由  C/C++ 完成核心部分,而 JavaScript 實(shí)現(xiàn)封裝和向外導(dǎo)出,如 buffer、fs、os 等。

所以在Node的模塊類(lèi)型中存在依賴(lài)層級(jí)關(guān)系:內(nèi)建模塊(C/C++)—> 核心模塊(JavaScript)—> 文件模塊。

使用require()十分的方便,但從 JavaScript 到 C/C++ 的過(guò)程十分復(fù)雜,總結(jié)來(lái)說(shuō)需要經(jīng)歷 C/C++ 層面內(nèi)建模塊的定義、(JavaScript)核心模塊的定義和引入以及(JavaScript)文件模塊的引入。

四、前端模塊規(guī)范

對(duì)比前后端的 JavaScript,瀏覽器端的 JavaScript 需要經(jīng)歷從同一個(gè)服務(wù)器端分發(fā)到多個(gè)客戶(hù)端執(zhí)行,通過(guò)網(wǎng)絡(luò)加載代碼,瓶頸在于寬帶;而服務(wù)器端 JavaScript 相同代碼需要多次執(zhí)行,通過(guò)磁盤(pán)加載,瓶頸在于 CPU 和內(nèi)存,所以前后端的 JavaScript 在 Http 兩端的職責(zé)完全不用。

Node 模塊的引入幾乎是同步的,而前端模塊如果同步引入,那腳本加載需要太長(zhǎng)的時(shí)間,所以 CommonJS 為后端 JavaScript 制定的規(guī)范不適合前端。而后出現(xiàn) AMD 和 CMD 用于前端應(yīng)用場(chǎng)景。

4.1 AMD 規(guī)范

AMD 即異步模塊定義(Asynchronous Module Definition),模塊定義為:

define(id?, dependencies?, factory);

AMD 模塊需要用define明確定義一個(gè)模塊,其中模塊id與依賴(lài)dependencies是可選的,factory的內(nèi)容就是實(shí)際代碼的內(nèi)容。例如指定一些依賴(lài)到模塊中:

define(['dep1', 'dep2'], function(){
    // module code
});

require.js 實(shí)現(xiàn) AMD 規(guī)范的模塊化,感興趣的可以查看 require.js 的文檔。

4.2 CMD 規(guī)范

CMD 模塊的定義更加簡(jiǎn)單:

 define(factory);

定義的模塊同 Node 模塊一樣是隱式包裝,在依賴(lài)部分支持動(dòng)態(tài)引入,例如:

 define(function(require, exports, module){
     // module code
 });

requireexports、module通過(guò)形參傳遞給模塊,需要依賴(lài)模塊時(shí)直接使用require()引入。

看完上述內(nèi)容,你們對(duì)Node中模塊實(shí)現(xiàn)過(guò)程是怎么樣的有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

本文題目:Node中模塊實(shí)現(xiàn)過(guò)程是怎么樣的
本文URL:http://aaarwkj.com/article2/igiioc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、ChatGPT、域名注冊(cè)、企業(yè)網(wǎng)站制作、網(wǎng)站策劃、企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名
亚洲高清成人综合网站| 国产91九色视频在线| 伊人激情久久综合中文字幕| 日韩国产一区二区三区精品| 日韩中文字幕视频一区| 中文字幕久精品视频免费| 亚洲国产精品综合久久久| 一区二区三区乱码av| 伊人激情久久综合中文字幕 | 欧洲亚洲国产一区二区| 四虎在线观看永久地址| 夫妻的世界电影完整版| 麻豆影片在线免费观看| 国产精品毛片av在线| 亚洲免费视频一二三区| 亚洲一区二区三区黄色| 色国产精品一区在线观看| 丝袜美腿亚洲欧美日韩| 精品国产91乱码一区二区三区| 国产白丝精品爽爽久久| 欧美日韩精品激情一区二区| 日韩精品一区二区三区四区在线视频 | 无毛亚洲视频在线观看| 风间由美亚洲一区二区三区| 国产亚洲黄片免费在线观看| 日韩精品高清中文字幕| 久久精品性少妇一区二区三区| 国产精品久久久久精品日日三级| 国产成人av中文字暮在线| 亚洲综合中文字幕精品| 三级精品一区二区三区| 91久久一区二区秋霞免费| 大屁股白浆一区二区三区| 国产三级亚洲三级在线理论| 日本特黄特色高清免费大片| 久久午夜人妻一区二区| 久草视频免费福利资源站| 亚洲熟女午夜毛片av毛片| 亚洲女同中文字幕在线| 青草草在线观看视频| 婷婷不卡中文字幕三区|