最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node對CommonJS的模塊規(guī)范

 更新時間:2019年11月06日 08:30:52   作者:wangxiaoxaio  
這篇文章主要介紹了Node對CommonJS的模塊規(guī)范,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

Node能夠以一種相對程度的的姿態(tài)出現(xiàn),離不開CommonJS規(guī)范的影響。Node借鑒CommonJS的Modules規(guī)范實現(xiàn)了一套非常易用的模塊系統(tǒng),NPM對packages規(guī)范的完好支持使得Node應用在開發(fā)過程中事半功倍。

在Node中引用模塊,需要經歷如下三個步驟。

1. 路徑分析

Node中的模塊分為核心模塊和文件模塊 。

核心模塊是由Node提供的模塊,它們在Node源代碼的編譯過程中就編譯進了二進制執(zhí)行文件,在Node進程啟動時,核心模塊就被直接加載進內存中,所以在引用核心模塊時,文件定位和編譯執(zhí)行這兩個步驟可以省略,并且在路徑分析中優(yōu)先判斷,所以它的加載速度時最快的。通過require引用核心模塊時,直接引用即可。如 require('http')

文件模塊是用戶編寫的模塊,它是在運行時動態(tài)加載的,需要完整的路徑分析,文件定位,編譯執(zhí)行的過程,所以它的速度比核心模塊慢。引用文件模塊的方式分為三種:

1.以.或..開始的相對路徑文件模塊。

2.以/開始的絕對路徑文件模塊。

3.非路徑形式的文件模塊(自定義模塊)。

1,2兩種方法用于引用用戶自己編寫的模塊,require會將路徑轉為真實路徑,并以真實路徑作為索引,將編譯執(zhí)行的結果(對象)存放在緩存中,由于指定了明確的文件位置,其加載速度慢于核心模塊,快于自定義模塊。第3中方式用于引用下載的第三方模塊,這類模塊的查找是最費時的。這里有一個 模塊路徑 的概念。自定義模塊的查找速度慢的原因就在于此。

/**
   通過以下代碼,可以看出模塊路徑的生成規(guī)則如下:當前目錄下的node_modules目錄,父目錄下的node_modules目錄,沿路徑向上逐級遞歸,直到根目錄下的node_modules目錄。
 */
 //a.js
 console.log(module.paths) 
 //將打印出如下結果
 [ 'H:\\Files\\qiuzhao\\please-offer\\node_modules',
  'H:\\Files\\qiuzhao\\node_modules',
  'H:\\Files\\node_modules',
 'H:\\node_modules' 
 ]

1. require('../a.js')
2. require('/a.js')
3. require('koa')

2. 文件定位

1) 文件擴展名:CommonJS規(guī)范允許在標識符中不包含文件擴展名,這時候Node會按照.js,.json,.node的次序補足擴展名,依次嘗試。

2)目錄分析和包(自定義模塊):在分析提供給require的標識符的過程中,在文件擴展名的依次嘗試后,依然沒有得到對應的文件,卻得到一個目錄,這在引用自定義模塊并沿著模塊路徑逐個進行查找時經常會出現(xiàn),此時Node會將目錄當做一個包來處理。這種情況下,Node首先會在當前目錄下查找package.json(包描述文件),通過JSON.parse()解析出對象后,從中取出main屬性指定的文件名進行定位,視情況而定會j擴展名的分析。如果main屬性指定的文件名錯誤或者根本就沒有package.json文件,Node會將index當做默認文件名,然后進行擴展名的依次嘗試。如果在目錄分析的過程中沒有成功定位到任何文件,則進入模塊路徑的下一個路徑進行查找,如果模塊路徑數(shù)組遍歷完畢仍未找到文件,則拋出錯誤。

3. 編譯執(zhí)行

在Node中,每個文件都是一個模塊,每個模塊都是一個對象,這個對象的定義如下:

function Module(id,parent){
    this.id = id
    this.exports = {}
    this.parent = parent
    if(parent&&parent.children){
      parent.push(this)
    }
    this.filename = null
    this.loaded = false
    this.children = []  //當前模塊引用的其他模塊會存儲在這里
  }

在成功定位到文件后,首先Node會 新建一個對象 ,然后會將文件內容載入并編譯執(zhí)行,并 將模塊的exports屬性返回給調用方 。針對不同擴展名的文件,有不同的載入方法,通過 require.extensions 可以查看系統(tǒng)以及支持的文件加載方式。

1).js文件:通過fs模塊 同步 讀取文件后編譯執(zhí)行。

在編譯該類型的文件時,Node會對獲取得文件內容進行頭尾的包裝,在頭部添加 (function(exports,require,module,__filename,__dirname){\n ,在尾部添加 \n}) 。一個正常的js文件會被包裝成如下的樣子:

(function(exports,require,module,__dirname,__filename){
   ... 
  })  //從這里可以看出,node對模塊的實現(xiàn),也借鑒了前端js經常使用的利用函數(shù)作用域還形成一個獨立的空間,以防污染全局作用域,這里node包裝了這一過程。

包裝之后的代碼會通過vm原生模塊的runInThisContext()方法執(zhí)行(類似eval),返回一個具體的function對象(runInThisContext()的作用在這里就是聲明一個函數(shù)),最后,將當前模塊對象(別忘了Node在成功定位到文件后,會首先創(chuàng)建一個module對象)的exports屬性,require方法,module本身,以及在之前兩步中得到的完整文件路徑和文件目錄作為參數(shù)傳遞給這個函數(shù)。這里有一點經典的例子:

//當我們想為模塊的輸出定義一個全新的對象時
  
  //error
  exports = {}
  
  
  //right
  module.exports = {}
  
  //這樣做的原因時,exports和modlue.exports指向的是同一個對象,而exports={}這種方式,不會影響module.exports指向的對象。Node真正返回給調用者的是module.exports
var val = 10
  var chageVal = function(val){
    val = 100
    console.log(val)
  }
  changeVal(val) //100
  console.log(val) //
  
  /----------------------/
  
  var obj = {
    age:12
  }
  
  var changeName = function(obj){
    obj = {
      age:21
    }
    console.log(obj.age)
  }
  
  changeName(obj) //21
  console.log(obj.age) //12
  
  //出現(xiàn)這種現(xiàn)象的原因是,當調用函數(shù)時,傳入的是變量的副本。

2).node文件:這是使用C/C++編寫的擴展文件,通過dlopen()方法加載最后編譯執(zhí)行的結果。dlopen()方法在不同平臺下有不同的實現(xiàn),通過libuv兼容層封裝。實際上,.node的模塊文件不需要編譯,因為它是編寫C/C++模塊之后編譯生成的,這里只有加載和執(zhí)行的過程,沒有編譯的過程。在執(zhí)行的過程中,模塊的exports對象與.node模塊產生聯(lián)系,然后返回給調用者。

3).json文件:通過fs模塊同步讀取文件后,使用JSON.parse()解析后返回結果。 這種類型的文件是三者中編譯最簡單的,Node利用fs模塊同步讀取文件內容后,調用JSON.parse()將其解析成對象,然后將其賦值給模塊對象的exports,以供外部調用。

4).其他擴展名文文件:被當做.js文件進行處理。

模塊的緩存

與前端瀏覽器會緩存靜態(tài)腳本文件已提高性能一樣,Node對引用的模塊都會進行緩存,以減少二次引入時的開銷,不同之處在于,瀏覽器緩存的是文件,Node緩存的是編譯和執(zhí)行后的對象。require()方法對相同模塊的二次加載一律采用緩存優(yōu)先的方式,這是第一優(yōu)先級的。每一個編譯成功的模塊都會將其文件路徑做為索引緩存在Module._cache對象上,Module._cache會被賦值給require()方法的cache屬性,所以可以通過require.cache還查看已經緩存的模塊。如果不想使用緩存的模塊,可以在被引用的模塊內添加 delete require.cache[module.filename] 。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • node模塊機制與異步處理詳解

    node模塊機制與異步處理詳解

    這篇文章主要介紹了node模塊機制與異步處理詳解的相關資料,需要的朋友可以參考下
    2016-03-03
  • node.js中的fs.fchmod方法使用說明

    node.js中的fs.fchmod方法使用說明

    這篇文章主要介紹了node.js中的fs.fchmod方法使用說明,本文介紹了fs.fchmod的方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • node里的filesystem模塊文件讀寫操作詳解

    node里的filesystem模塊文件讀寫操作詳解

    這篇文章主要為大家介紹了node里的filesystem模塊文件讀寫操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Node實現(xiàn)前端本地開發(fā)接口代理服務

    Node實現(xiàn)前端本地開發(fā)接口代理服務

    本文主要介紹了Node實現(xiàn)前端本地開發(fā)接口代理服務,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • Node.js API詳解之 timer模塊用法實例分析

    Node.js API詳解之 timer模塊用法實例分析

    這篇文章主要介紹了Node.js API詳解之 timer模塊用法,結合實例形式分析了Node.js API中timer模塊基本功能、原理、用法及操作注意事項,需要的朋友可以參考下
    2020-05-05
  • nodejs基于express實現(xiàn)文件上傳的方法

    nodejs基于express實現(xiàn)文件上傳的方法

    這篇文章主要介紹了nodejs基于express實現(xiàn)文件上傳的方法,結合實例形式分析了nodejs基于express框架實現(xiàn)文件上傳功能的具體步驟與相關操作技巧,需要的朋友可以參考下
    2018-03-03
  • 使用 Node.js 實現(xiàn)圖片的動態(tài)裁切及算法實例代碼詳解

    使用 Node.js 實現(xiàn)圖片的動態(tài)裁切及算法實例代碼詳解

    這篇文章主要介紹了使用 Node.js 實現(xiàn)圖片的動態(tài)裁切功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-09-09
  • Nodejs中使用captchapng模塊生成圖片驗證碼

    Nodejs中使用captchapng模塊生成圖片驗證碼

    本篇文章主要介紹了Nodejs中使用captchapng模塊實現(xiàn)圖片驗證碼,非常具有實用價值,需要的朋友可以參考下
    2017-05-05
  • Nodejs實現(xiàn)用戶注冊功能

    Nodejs實現(xiàn)用戶注冊功能

    本文通過實例代碼給大家介紹了Nodejs實現(xiàn)用戶注冊功能,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • 快速了解Node中的Stream流是什么

    快速了解Node中的Stream流是什么

    今天小編就為大家分享一篇關于快速了解Node中的Stream流是什么,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02

最新評論

衡水市| 湘潭县| 芦山县| 杭锦后旗| 新田县| 赤城县| 邹城市| 麻阳| 新绛县| 巴林右旗| 昌邑市| 双流县| 万山特区| 梅河口市| 岱山县| 临泉县| 土默特左旗| 阿拉善左旗| 梨树县| 连云港市| 同江市| 平山县| 九龙城区| 屏山县| 宁强县| 灵武市| 镇康县| 彰化市| 岳池县| 镶黄旗| 师宗县| 肥东县| 亚东县| 凌海市| 宝兴县| 林甸县| 苍梧县| 正蓝旗| 泗水县| 灵台县| 吉安市|