搜尋

commonJS詳解

Mar 09, 2018 pm 02:08 PM
javascript詳解

這次帶給大家commonJS詳解,使用commonJS詳解的注意事項有哪些,下面就是實戰案例,一起來看一下。

commonJS概述

所有程式碼都運行在模組作用域,不會污染全域作用域。
模組可以多次加載,但是只會在第一次加載時運行一次,然後運行結果就被緩存了,以後再加載,就直接讀取緩存結果。要讓模組再次運行,必須清除快取。
模組載入的順序,按照其在程式碼中出現的順序。

2.module物件

每個模組內部,都有一個module對象,代表目前模組。它有以下屬性。

console.log(module.id) //模块的识别符,通常是带有绝对路径的模块文件名。console.log(module.filename) //模块的文件名,带有绝对路径。console.log(module.loaded) //返回一个布尔值,表示模块是否已经完成加载。console.log(module.parent) //返回一个对象,表示调用该模块的模块。console.log(module.children) //返回一个数组,表示该模块要用到的其他模块。console.log(module.exports) //表示模块对外输出的值。

2.1 module.exports屬性

module.exports屬性表示當前模組對外輸出的接口,其他檔案載入該模組,實際上就是讀取module.exports變數。

2.2 exports變數

為了方便,Node為每個模組提供一個exports變量,指向module.exports。這等同在每個模組頭部,有一行這樣的命令:

var exports = module.exports;(commonJS隐式做了这个赋值)

這樣做的好處是,在對外輸出模組介面時,可以向exports物件添加方法暴露出去。
因此如果改變了module.exports,但還想使用export.xxx的方式暴露一些東西,那就只好我們自己來寫exports = module.exports;
栗子:

module.exports = songthing;//接下来把exports指回来exports = module.exports;//常见写法是:exports = module.exports = something;

3 .AMD規範與CommonJS規範的兼容性

CommonJS規範載入模組是同步的,只有載入完成,才能執行後面的操作。 AMD規範則是非同步載入模組,允許指定回呼函數。由於Node.js主要用於伺服器編程,模組檔案一般都已經存在於本地硬碟,所以載入起來比較快,不用考慮非同步載入的方式,所以CommonJS規範比較適用。但是,如果是瀏覽器環境,要從伺服器端載入模組,這時就必須採用非同步模式,因此瀏覽器端一般採用AMD規範。

define(['package/lib'], function(lib){  function foo(){
    lib.log('hello world!');
  }  return {    foo: foo
  };
});

AMD規範允許輸出的模組相容於CommonJS規範,這時define方法需要寫成下面這樣:

define(function (require, exports, module){  var someModule = require("someModule");  var anotherModule = require("anotherModule");
  someModule.doTehAwesome();
  anotherModule.doMoarAwesome();
  exports.asplode = function (){
    someModule.doTehAwesome();
    anotherModule.doMoarAwesome();
  };
});

4.require指令

4.1基本用法

Node使用CommonJS模組規範,內建的require指令用來載入模組檔。
require指令的基本功能是,讀入並執行一個JavaScript文件,然後傳回該模組的exports物件。如果沒有發現指定模組,會報錯。 (說白了就是將另一個檔案中暴露的值,引用到本檔案中。)

// example.jsvar invisible = function () {  console.log("invisible");
}
exports.message = "hi";
exports.say = function () {  console.log(message);
}

運行下面的命令,可以輸出exports物件。

//someelse.jsvar example = require('./example.js');console.log(example);// {//   message: "hi",//   say: [Function]// }

如果模組輸出的是一個函數,那就不能定義在exports物件上面,而要定義在module.exports變數上面。

//example2.jsmodule.exports = function () {  console.log("hello world")
}require('./example2.js')()

上面程式碼中,require指令呼叫自身,等於是執行module.exports,因此會輸出 hello world。

4.2載入規則

require指令用於載入文件,後綴名稱預設為.js。

var foo = require('foo');//  等同于var foo = require('foo.js');

根據參數的不同格式,require指令去不同路徑尋找模組檔案:

(1)如果參數字串以「/」開頭,則表示載入的是一個位於絕對路徑的模組檔。例如,require('/home/marco/foo.js')將會載入/home/marco/foo.js。
(2)如果參數字串以「./」開頭,則表示載入的是位於相對路徑(跟目前執行腳本的位置相比)的模組檔案。例如,require('./circle')將載入目前腳本相同目錄的circle.js。
(3)如果參數字串不以「./「或」/「開頭,則表示載入的是一個預設提供的核心模組(位於Node的系統安裝目錄中),或一個位於各級node_modules目錄的已安裝模組(全域安裝或局部安裝)。

舉例來說,腳本/home/user/projects/foo.js執行了require('bar.js')指令,Node會依序搜尋以下檔案。

/usr/local/lib/node/bar.js
/home/user/projects/node_modules/bar.js
/home/user/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js

這樣設計的目的是,使得不同的模組可以將所依賴的模組本地化。
(4)如果參數字串不以「./「或」/「開頭,而且是路徑,例如require('example-module/path/to/file'),則會先找到example-module的位置,然後再以它為參數,找到後續路徑。
(5)如果指定的模組檔案沒有發現,Node會嘗試為檔案名稱新增.js、.json、.node後,再去搜尋。 .js件會以文字格式的JavaScript腳本檔案解析,.json檔案會以JSON格式的文字檔案解析,.node檔案會以編譯後的二進位檔案解析。
(6)如果想得到require指令載入的確切檔名,使用require.resolve()方法。

4.3目錄的載入規則

通常,我们会把相关的文件会放在一个目录里面,便于组织。这时,最好为该目录设置一个入口文件,让require方法可以通过这个入口文件,加载整个目录。
在目录中放置一个package.json文件,并且将入口文件写入main字段。下面是一个例子。

// package.json{ "name" : "some-library",  "main" : "./lib/some-library.js" }
require发现参数字符串指向一个目录以后,会自动查看该目录的package.json文件,然后加载main字段指定的入口文件。如果package.json文件没有main字段,或者根本就没有package.json文件,则会加载该目录下的index.js文件或index.node文件。

4.4模块的缓存

第一次加载某个模块时,Node会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的module.exports属性。

require('./example.js');require('./example.js').message = "hello";require('./example.js').message// "hello"

上面代码中,连续三次使用require命令,加载同一个模块。第二次加载的时候,为输出的对象添加了一个message属性。但是第三次加载的时候,这个message属性依然存在,这就证明require命令并没有重新加载模块文件,而是输出了缓存。
如果想要多次执行某个模块,可以让该模块输出一个函数,然后每次require这个模块的时候,重新执行一下输出的函数。
所有缓存的模块保存在require.cache之中,如果想删除模块的缓存,可以像下面这样写。

// 删除指定模块的缓存delete require.cache[moduleName];// 删除所有模块的缓存Object.keys(require.cache).forEach(function(key) {  delete require.cache[key];
})

注意,缓存是根据绝对路径识别模块的,如果同样的模块名,但是保存在不同的路径,require命令还是会重新加载该模块。

4.5环境变量NODE_PATH

Node执行一个脚本时,会先查看环境变量NODE_PATH。它是一组以冒号分隔的绝对路径。在其他位置找不到指定模块时,Node会去这些路径查找。

可以将NODE_PATH添加到.bashrc。
export NODE_PATH="/usr/local/lib/node"

所以,如果遇到复杂的相对路径,比如下面这样:

var myModule = require('../../../../lib/myModule');

有两种解决方法,一是将该文件加入node_modules目录,二是修改NODE_PATH环境变量,package.json文件可以采用下面的写法。

{  "name": "node_path",  "version": "1.0.0",  "description": "",  "main": "index.js",  "scripts": {    "start": "NODE_PATH=lib node index.js"
  },  "author": "",  "license": "ISC"}

NODE_PATH是历史遗留下来的一个路径解决方案,通常不应该使用,而应该使用node_modules目录机制。

4.6模块的循环加载

如果发生模块的循环加载,即A加载B,B又加载A,则B将加载A的不完整版本。

// a.jsexports.x = 'a1';console.log('a.js ', require('./b.js').x);
exports.x = 'a2';// b.jsexports.x = 'b1';console.log('b.js ', require('./a.js').x);
exports.x = 'b2';// main.jsconsole.log('main.js ', require('./a.js').x);console.log('main.js ', require('./b.js').x);

上面代码是三个JavaScript文件。其中,a.js加载了b.js,而b.js又加载a.js。这时,Node返回a.js的不完整版本,所以执行结果如下。(也就是说,虽然这样去require看似会造成a.js和b.js循环引用,但commonJS会在将循环的点剪断循环,并对剪断处所在的a.js终止执行,b得到了第一个x值。)

$ node main.js
b.js  a1
a.js  b2
main.js  a2
main.js  b2

修改main.js,再次加载a.js和b.js。

// main.jsconsole.log('main.js ', require('./a.js').x);console.log('main.js ', require('./b.js').x);console.log('main.js ', require('./a.js').x);console.log('main.js ', require('./b.js').x);

执行上面代码,结果如下。

$ node main.js
b.js  a1
a.js  b2
main.js  a2
main.js  b2
main.js  a2
main.js  b2

上面代码中,第二次加载a.js和b.js时,会直接从缓存读取exports属性,所以a.js和b.js内部的console.log语句都不会执行了。

4.7 require.main

require方法有一个main属性,可以用来判断模块是直接执行,还是被调用执行。
直接执行的时候(node module.js),require.main属性指向模块本身。

require.main === module// true

调用执行的时候(通过require加载该脚本执行),上面的表达式返回false。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

相关阅读:

用jq发送多个ajax然后执行回调的小技巧

怎样使用伪元素first-letter让文字首字母大写

JavaScript的函数重载详解

chrome的内存不足频繁崩溃怎么处理

以上是commonJS詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

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

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

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

JavaScript是用C編寫的嗎?檢查證據JavaScript是用C編寫的嗎?檢查證據Apr 25, 2025 am 12:15 AM

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

JavaScript的角色:使網絡交互和動態JavaScript的角色:使網絡交互和動態Apr 24, 2025 am 12:12 AM

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

C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

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

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

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

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

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

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 英文版

SublimeText3 英文版

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