node.js module初步理解

轉摘自http://www.cnblogs.com/dolphinX/p/3485260.htmlhtml

 

 在開發一個複雜的應用程序的時候,咱們須要把各個功能拆分、封裝到不一樣的文件,在須要的時候引用該文件。沒人會寫一個幾萬行代碼的文件,這樣在可讀性、複用性和維護性上都不好,幾乎全部的編程語言都有本身的模塊組織方式,好比Java中的包、C#中的程序集等,node.js使用模塊和包來組織,其機制實現參照了CommonJS標準,雖未徹底遵照,但差距不大,使用起來很是簡單。前端

什麼是模塊

在node.js中模塊與文件是一一對應的,也就是說一個node.js文件就是一個模塊,文件內容多是咱們封裝好的一些JavaScript方法、JSON數據、編譯過的C/C++拓展等,在關於node.js的誤會提到過node.js的架構node

其中http、fs、net等都是node.js提供的核心模塊,使用C/C++實現,外部用JavaScript封裝。npm

建立、加載模塊

模塊在node.js中的概念很簡單,看看如何建立一個咱們本身的模塊供開發複用。編程

在node.js中建立模塊很是簡單,一個文件就是一個模塊,因此咱們建立一個test.js文件就建立了一個模塊閉包

test.js架構

複製代碼
var name='';

function setName(n){
    name=n;
} 

function printName(){
    console.log(name);
}
複製代碼

 問題是怎麼使外部訪問這個module,咱們知道客戶端的JavaScript使用script標籤引入JavaScript文件就能夠訪問其內容了,但這樣帶了的弊端不少,最大的就是做用域相同,產生衝突問題,以致於前端大師們想出了當即執行函數等方式,利用閉包解決。node.js使用exports和require對象來解決對外提供接口和引用模塊的問題。編程語言

咱們能夠把模塊中但願被外界訪問的內容定義到exports對象中,對test.js稍做修改就能夠了函數

test.jspost

複製代碼
var name='';

function setName(n){
    name=n;
} 

function printName(){
    console.log(name);
}

exports.setName=setName;
exports.printName=printName;
複製代碼

這樣咱們在相同路徑下建立index.js,使用require引用一下test.js module

index.js

var test=require('./test');

test.setName('Byron');
test.printName();

exports一個對象

有時候咱們但願模塊對外提供的使一個對象,修改一下test.js

test.js

複製代碼
var Student=function(){
    var name='';

     this.setName=function(n){
        name=n;
    }; 

    this.printName=function(){
        console.log(name)    ;
    };
};

exports.Student=Student;
複製代碼

 這樣咱們對外提供了一個Student類,在使用的時候須要這樣

var Student=require('./test').Student;
var student=new Student();
student.setName('Byron');
student.printName();

 require('./test').Student 很醜陋的樣子,咱們能夠簡單修改一下exports方式,使require優雅一些

test.js

複製代碼
var Student=function(){
    var name='';

     this.setName=function(n){
        name=n;
    }; 

    this.printName=function(){
        console.log(name)    ;
    };
};

module.exports=Student;
複製代碼

 這樣咱們的require語句就能夠優雅一些了

var Student=require('./test');

 

很神奇的樣子,不是說好的exports是模塊公開的接口嘛,那麼module.exports是什麼東西?

module.exports與exports

事實的狀況是醬紫的,其實module.exports纔是模塊公開的接口,每一個模塊都會自動建立一個module對象,對象有一個modules的屬性,初始值是個空對象{},module的公開接口就是這個屬性——module.exports。既然如此那和exports對象有毛線關係啊!爲何咱們也能夠經過exports對象來公開接口呢?

爲了方便,模塊中會有一個exports對象,和module.exports指向同一個變量,因此咱們修改exports對象的時候也會修改module.exports對象,這樣咱們就明白網上盛傳的module.exports對象不爲空的時候exports對象就自動忽略是怎麼回事兒了,由於module.exports經過賦值方式已經和exports對象指向的變量不一樣了,exports對象怎麼改和module.exports對象不要緊了。

大概就是這麼過程

複製代碼
module.exports=exports={};
......

module.exports=new Object();

exports=xxx;//和new Object沒有關係了,最後返回module.exports,因此改動都無效了
複製代碼

一次加載

不管調用多少次require,對於同一模塊node.js只會加載一次,引用屢次獲取的還是相同的實例,看個例子

test.js

複製代碼
var name='';

function setName(n){
    name=n;
} 

function printName(){
    console.log(name);
}

exports.setName=setName;
exports.printName=printName;
複製代碼

 

index.js

var test1=require('./test'),
    test2=require('./test');

test1.setName('Byron');
test2.printName();

 

 

執行結果並非'',而是輸出了test1設置的名字,雖然引用兩次,可是獲取的是一個實例

require搜索module方式

node.js中模塊有兩種類型:核心模塊和文件模塊,核心模塊直接使用名稱獲取,好比最長用的http模塊

var http=require('http');

 

在上面例子中咱們使用了相對路徑 './test'來獲取自定義文件模塊,那麼node.js有幾種搜索加載模塊方式呢?

  1. 核心模塊優先級最高,直接使用名字加載,在有命名衝突的時候首先加載核心模塊
  2. 文件模塊只能按照路徑加載(能夠省略默認的.js拓展名,不是的話須要顯示聲明書寫)
    1. 絕對路徑
    2. 相對路徑
  3. 查找node_modules目錄,咱們知道在調用 npm install <name> 命令的時候會在當前目錄下建立node_module目錄(若是不存在) 安裝模塊,當 require 遇到一個既不是核心模塊,又不是以路徑形式表示的模塊名稱時,會試圖 在當前目錄下的 node_modules 目錄中來查找是否是有這樣一個模塊。若是沒有找到,則會 在當前目錄的上一層中的 node_modules 目錄中繼續查找,反覆執行這一過程,直到遇到根 目錄爲止。
相關文章
相關標籤/搜索