跟我學Nodejs(三)--- Node.js模組

來源:互聯網
上載者:User

簡介及資料

    通過Node.js的官方API可以看到Node.js本身提供了很多核心模組 http://nodejs.org/api/ ,這些核心模組被編譯成二進位檔案,可以require('模組名')去擷取;核心模組具有最高的載入優先順序(有模組與核心模組同名時會體現)

    (本次主要說自訂模組)

    Node.js還有一類別模組為檔案模組,可以是JavaScript代碼檔案(.js作為檔案尾碼)、也可以是JSON格式文字檔(.json作為檔案尾碼)、還可以是編輯過的C/C++檔案(.node作為檔案尾碼);

    檔案模組訪問方式通過require('/檔案名稱.尾碼')    require('./檔案名稱.尾碼')    requrie('../檔案名稱.尾碼') 去訪問,檔案尾碼可以省略;以"/"開頭是以絕對路徑去載入,以"./"開頭和以"../"開頭表示以相對路徑載入,而以"./"開頭表示同級目錄下檔案,

    前面提到檔案尾碼可以省略,Nodejs嘗試載入的優先順序 js檔案 > json檔案 > node檔案

建立一個自訂模組

   以一個計數器為例

複製代碼 代碼如下:
var outputVal  = 0;     //輸出值
var increment = 1;    //增量
/* 設定輸出值 */
function seOutputVal (val) {
    outputVal = val;
}
/* 設定增量 */
function setIncrement(incrementVal){
    increment = incrementVal;
}
/* 輸出 */
function printNextCount()
{   
    outputVal += increment;
    console.log(outputVal) ;
}
function printOutputVal() {
    console.log(outputVal);
}
exports.seOutputVal = seOutputVal;
exports.setIncrement = setIncrement;
module.exports.printNextCount = printNextCount;
自訂模組 樣本源碼

樣本中重點在於exports和module.exports;提供了外部存取的介面,下面調用一下看看效果吧

調用自訂模組

複製代碼 代碼如下:
/*
    一個Node.js檔案就是一個模組,這個檔案可能是Javascript代碼、JSON或者編譯過的C/C++擴充。
    重要的兩個對象:
    require是從外部擷取模組
    exports是把模組介面公開   
*/
var counter = require('./1_modules_custom_counter');
console.log('第一次調用模組[1_modules_custom_counter]');
counter.seOutputVal(10);               //設定從10開始計數
counter.setIncrement (10);             //設定增量為10
counter.printNextCount();
counter.printNextCount();
counter.printNextCount();
counter.printNextCount();
/*
    require多次調用同一模組不會重複載入
*/
var counter = require('./1_modules_custom_counter');
console.log('第二次調用模組[1_modules_custom_counter]');
counter.printNextCount();
自訂模式調用 源碼

    運行可以發現通過exports和module.exports對外公開的方法都可以訪問!

    樣本中可以看到,我兩次通過require('./1_modules_custom_counter')擷取模組,但是第二次引用後調用printNextCount()方法確從60開始~~~

    原因是node.js通過requirerequire多次調用同一模組不會重複載入,Node.js會根據檔案名稱緩衝所有載入過的檔案模組,所以不會重新載入了

    注意:通過檔案名稱緩衝是指實際檔案名稱,並不會因為傳入的路徑形式不一樣而認會是不同的檔案    

    在我建立的1_modules_custom_counter檔案中有一個printOutputVal()方法,它並沒有通過exports或module.exports提供對外公開存取方法,

    如果1_modules_load檔案中直接存取運行會出現什麼樣的情況呢?

    答案是:TypeError: Object #<Object> has no method 'printOutputVal'

exports和module.exports 區別

經過上面的例子,通過exports和module.exports對外公開的方法都可以訪問!那既然兩種都能達到效果,但總得有點區別的吧~~~用個例子看看吧!

複製代碼 代碼如下:
var counter  = 0;    
exports.printNextCount = function (){   
    counter += 2;
    console.log(counter);
}
var isEq = (exports === module.exports);
console.log(isEq);
2_modules_diff_exports.js 檔案源碼

下面再建立個2_modules_diff_exports_load.js檔案調用一下

複製代碼 代碼如下:
var Counter = require('./2_modules_diff_exports');
Counter.printNextCount();

    調用後,執行結果如

    我在2_modules_diff_exports_load.js檔案中輸出了isEq的值  ( var isEq = (exports === module.exports); ),返回的true

    PS:注意是三個等號,如果不清楚自已查查資料吧!

不用急著下結論,把這兩個JS檔案分別改成module.exports對應的代碼

複製代碼 代碼如下:
//修改後的2_modules_diff_exports.js源碼如下
var counter  = 0;    
module.exports = function(){   
    counter += 10;
    this.printNextCount = function()
    {
        console.log(counter);   
    }
}
var isEq = (exports === module.exports);
console.log(isEq);

複製代碼 代碼如下:
//修改後的2_modules_diff_exports_load.js檔案源碼如下
var Counter = require('./2_modules_diff_exports');
var counterObj = new Counter();
counterObj.printNextCount();

    調用後,執行結果如

    我在2_modules_diff_exports_load.js檔案中輸出了isEq的值  ( var isEq = (exports === module.exports); ),返回的false,這與用先前得到的結果不一致!

    PS:不要用Counter.printNextCount();去訪問,你只會得到一個錯誤的提示

    API提供瞭解釋

    http://nodejs.org/api/modules.html

    Note that exports is a reference to module.exports making it suitable for augmentation only. If you are exporting a single item such as a constructor you will want to use module.exports directly instead
    exports僅僅是module.exports的一個地址引用。nodejs只會匯出module.exports的指向,如果exports指向變了,那就僅僅是exports不在指向module.exports,於是不會再被匯出

    參考其它理解:

    http://www.hacksparrow.com/node-js-exports-vs-module-exports.html

    http://zihua.li/2012/03/use-module-exports-or-exports-in-node/

    module.exports才是真正的介面,exports只不過是它的一個協助工具輔助。 最終返回給調用的是module.exports而不是exports。
    所有的exports收集到的屬性和方法,都賦值給了Module.exports。當然,這有個前提,就是module.exports本身不具備任何屬性和方法。
    如果,module.exports已經具備一些屬性和方法,那麼exports收集來的資訊將被忽略。

exports和module.exports 覆蓋

上面也也基本明白了exports和module.exports的關係和區別,但如果同時針對printNextCount()方法存在exports和module.exports,結果如何?

調用結果

    從結果可以看出,並沒有報錯,表示可以這麼定義,但最終module.exports覆蓋了exports

    雖然結果不會報錯,如果這麼用開發中難免會有一些問題存在,所以

    1.最好別分別定義module.exports和exports

    2.NodeJs開發人員建議匯出對象用module.exports,匯出多個方法和變數用exports

其它...

   API中還提供了其它的方法,就不細講了,在上面例子的基礎上自已動手一輸出就知道了

  module.id

  返回string類型的模組標識,一般為完全解析後的檔案名稱

  module.filename

  返回一個string類型的完全解析後檔案名稱

  module.loaded

  返回一個bool類型,表示是否載入完成

  module.parent

  返回引用該模組的模組

  module.children

  返回該模組引用的所有模組對象的數組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.