Node
應用程式由模組組成,其模組系統借鑒了CommonJS
模組規範,但是並未完全按照規範實現,而是根據自身需求增加了一些特性,算是CommonJS
模組規格的一個變種。
CommonJS概述
CommonJS
是社群提出的一種JavaScript
模組化規範,可以說是 JS
模組化歷程中最重要的一塊里程碑,它建構了一個美好的願景-JS
能夠在任何地方運行,但其實由於它的模組是同步載入的,只適合在服務端等其他本機環境,並不適合瀏覽器端等需要非同步載入資源的地方。
為了能讓JS
能夠在任何地方運行,CommonJS
制定了一些介面規範,這些介面覆蓋了模組、二進位、Buffer
# 、字元集編碼、I/O
流、進程環境、檔案系統、socket
、單元測試、web伺服器、網關、套件管理等等,雖然大部分都處於草案階段,但是其深深影響了Node
的發展。
下圖表示了Node
與瀏覽器、W3C
、CommonJS
以及ECMAScript
之間的關係,摘自《深入淺出NodeJS》
CommonJS的模組規格
CommonJS
的模組主要由模組引用、模組定義和模組標識三部分組成。
模組標識
模組標識對每個模組來說是唯一的,是它被引用時的依據,它必須是符合小駝峰命名的字串,或是檔案的相對路徑或絕對路徑。
require('fs')// fs是内建模块,执行时会被直接载入内存,无须路径标识 require('./moduleA')//导入当前目录的moduleA require('../moduleB')// 导入上一个目录的moduleB require('C://moduleC')// 绝对路径导入moduleC
模組引用
使用require()
來引用一個模組,這個方法接受一個模組識別作為參數,以此引入一個模組的API到目前上下文。
const fs = require('fs')// 引入内建的fs模块
模組定義
有導入自然也有導出,要將目前上下文中的方法或變數作為模組導出,需要使用內建的module.exports
對象,它是模組導出的唯一出口。
CommonJS
規格規定,每個模組內部,module
變數代表目前模組。這個變數是一個對象,它的exports
屬性(即module.exports
)是對外的介面。載入某個模組,其實是載入該模組的module.exports
屬性。
// moduleA.js模块 let moduleA = { name:"moduleA" } module.exports = { moduleA } // moduleB.js模块 // 导入moduleA const {moduleA} = require('./moduleA')
CommonJS
模組的特性如下:
- 每個模組有獨立的上下文,模組內的程式碼獨立執行,不會污染全域作用域。
- 模組可以被多次加載,但是只會在第一次加載時運行,運行結果會被緩存,後續再加載相同模組會直接讀取緩存結果,緩存存儲在
module. cache
中 - 模組的載入會依照程式碼順序執行。
Node的模組實作
Node
#導入模組需要經歷3
個步驟:路徑分析 -> 檔案定位 -> 編譯執行:
路徑分析:根據模組識別分析模組類型。
檔案定位:根據模組類型和模組識別碼找到模組所處位置。
編譯執行:將檔案編譯成機器碼執行,中間需要經過一連串轉換。
【推薦學習:《nodejs 教學》】
模組類型分為內建模區塊與使用者模組:
內建模區塊:內建模區塊由
Node
提供,已經被編譯成二進位執行文件,在node
執行時,內建模區塊會直接載入內存,因此我們可以直接引入,它的加載速度很快,因為它不需要經過文件定位和編譯執行這2
個步驟。檔案模組:使用
js
或C
等寫的擴充模組,執行時需要先被編譯成二進位機器碼。需要經過上述三大步驟。
模組快取
#不管是內建模區塊還是檔案模組,node
在第一次載入後都會將結果快取起來,下次載入相同模組時,會先從快取中查找,如果能查找到則直接從快取中讀取,快取的結果是模組編譯和執行後的對象,是所有模組中加載最快的。
路径分析
路径分析依据的是模块标识符,模块标识符有以下几种类型:
- 内建模块标识,例如
fs
,path
等,不需要编译,node
运行时被直接载入内存等待导入。 - 相对路径模块标识:使用相对路径描述的文件模块
- 绝对路径模块标识:使用绝对路径描述的文件模块
- 自定义模块标识:通常是
node_modules
中的包,引入时也不需要写路径描述,node
有一套算法来寻找,是所有模块标识中分析速度最慢的。
文件定位
文件定位主要包括文件扩展名分析、目录和包的处理。如果文件定位结束时都没找到任何文件,则会抛出文件查找失败的异常。
文件扩展名分析
由于模块标识可以不添加文件扩展名,因此Node
会按.js
、.json
、.node
的次序依次补足扩展名来尝试加载,尝试加载的过程需要调用fs
模块同步阻塞式地判断文件是否存在,因此为了提高性能,可以在使用require()
导入模块时,参数带上文件扩展名,这样会加快文件定位速度。
目录、包的处理
在分析文件扩展名时,可能得到的是一个目录,此时Node
会将其作为一个包处理,用查找包的规则来查找:在当前目录下查找package.json
,获得其中定义的main
属性指定的文件名,以它来作为查找的入口,如果没有package.json
,则默认将目录下的index
当前默认文件名,然后依次查找index.js
、index.json
、index.node
。
编译执行
编译和执行是模块导入的最后一个步骤,node
会先创建一个Module
实例,代表当前模块。它有以下属性:
-
module.id
模块的识别符,通常是带有绝对路径的模块文件名。 -
module.filename
模块的文件名,带有绝对路径。 -
module.loaded
返回一个布尔值,表示模块是否已经完成加载。 -
module.parent
返回一个对象,表示调用该模块的模块。 -
module.children
返回一个数组,表示该模块要用到的其他模块。 -
module.exports
表示模块对外输出的值。
通过文件定位得到的信息,Node
再载入文件并编译。对于不同的文件扩展名,其载入方法也有所不同:
-
.js
文件:通过fs
模块同步读取文件后编译执行。 -
.node
文件:这是C/C++
编写的扩展文件,通过dlopen()
方法加载。 -
.json
文件:通过fs
模块读取后,用JSON.parse()
解析返回结果。 - 其余扩展名一律当
.js
文件载入
每一个载入的模块都会被缓存,可以通过require.cache
来查看。
使用ES-Module
目前,在node
中使用ES-Module
属于实验性功能,从8.5
开始支持,执行时需要加上--experimental-modules
参数。从12.17.0 LTS
开始,去掉了--experimental-modules
,现在可以通过使用.mjs
文件代替.js
文件或在package.json
中指定 type
为 module
两种方式使用。
// package.json { "name": "esm-project", "version": "1.0.0", "main": "index.js", "type": "module", ... }
ES-Module
相比于CommonJS
的Module
机制,最大不同是ES-Module
对导出模块的变量、对象是动态引用,而且是在编译阶段暴露模块的导入接口,因此可以进行静态分析;而CommonJS-Module
是运行时同步加载,且输出的是导出模块的浅拷贝。除此之外,ES-Module
支持加载CommonJS-Module
,而反过来则不行。
其次,Node
规定 ES6
模块之中不能使用 CommonJS
模块的特有的一些内部变量,这是因为ES-Module
顶层this
指向undefined
,CommonJS
模块的顶层this
指向当前模块,而这些内部变量作为顶层变量能被直接使用。
CommonJS
的内部变量有:
arguments
require
#module
- ##exports
m
- __filename
- __dirname
#Node
模組的載入是同步的,只有載入完成,才能執行後面的操作。每一個檔案就是一個模組,有自己的作用域。每個模組內部,
module
物件代表了目前模組,它的exports
屬性作為目前模組的導出介面。導入的模組是導出模組的一個淺拷貝。
更多程式相關知識,請造訪:程式設計影片! !
以上是什麼是CommonJS模組規格? Nodejs模組機制淺析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。