Node.js的模块系统相似于C/C++的文件引用,能够声明对象,也能够定义类 建立对象。html
你们这么理解,就简单了。node
为了让Node.js的文件能够相互调用,Node.js提供了一个简单的模块系统。json
模块是Node.js应用程序的基本组成部分,文件和模块是一一对应的。缓存
换言之,一个Node.js文件就是一个模块,这个文件多是Javascript代码、JSON或者编译过的C/C++扩展。服务器
这个实例演示的是,在hello.js中建立一个方法,而后在主程序main.js中调用这个方法。函数
在Node.js中,建立一个模块很是简单,你们跟着作一下就OK了。步骤以下:post
步骤1:在E:\NodejsDemo文件夹中,建立一个“hello.js”文件,代码以下:ui
1 exports.welcome = function(){ 2 console.log("Welcome to My Blog!"); 3 }
上述代码中,咱们使用exports对象,把welcome做为当前hello.js模块的访问接口。this
这样,在其余的模块(js文件)中,使用require命令,引入当前js文件,便可直接访问welcome了。url
步骤2:同目录下,咱们建立一个“main.js”文件,做为要执行的主程序,引入hello.js文件,执行welcome方法,代码以下:
1 var Hello = require('./hello'); // 引入hello.js模块(文件) 2 Hello.welcome(); // 访问hello.js文件中的welcome函数
上述代码中,咱们使用require函数,引入hello.js文件。
而后,咱们把引入的hello.js模块,存入了一个本地变量“Hello”中。
最后,咱们使用本地变量“Hello”调用welcome函数,也就是访问了hello.js模块中的welcome对外接口函数。
注意:这里引入hello.js模块的时候,咱们并无加后缀,“./”表示当前目录,Node.js默认后缀为“.js”。
步骤3:启动DOS,进入目录,执行“node main.js”运行主程序:
OK,你们发现,咱们调用welcome方法以后,执行的是hello.js文件中建立的welcome函数。
这个例子,你们想我开头所说的理解,其实很是简单。重点是exports和require。
require命令咱们在以前“Node.js 教程 02 - 经典的Hello World”已经接触过了。
Node.js 提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。
有没有感受,这个例子很像Java/.NET中的定义类、声明对象、调用方法?
Js大牛们知道,在Javascript中,咱们能够“定义类、实例化对象”。
那咱们若是想把一个对象封装到模块中,应该怎么办呢?
按照上面的实例一,咱们照葫芦画瓢:定义一个person类,引入实例化,并赋值,最后调用函数。
步骤1:建立一个“person.js”文件,做为要引入的模块文件,代码以下:
1 function Person(){ 2 var name; 3 this.setName = function(_name){ 4 name = _name; 5 } 6 7 var url; 8 this.setUrl = function(_url){ 9 url = _url; 10 } 11 12 this.sayHello = function(){ 13 console.log("Welcome to my blog!\n" + url); 14 console.log("My name is " + name +". Nice to meet you!"); 15 } 16 } 17 18 module.exports = Person;
上述代码中,咱们建立了一个Person对象,包含两个需赋值参数及一个输出函数。
重点是最后一句: module.exports = Person;
模块接口的惟一变化是使用 module.exports = Person 代替了 exports.world = function(){} 。
在外部引用该模块时,其接口对象就是要输出的 Person 对象自己,而不是原先的 exports。
步骤2:建立主程序“main.js”,引入person.js模块,实例初始化并调用,代码以下:
1 var Person = require('./person'); 2 3 var person = new Person(); 4 person.setName("GuYing"); 5 person.setUrl("http://www.cnblogs.com/LonelyShadow"); 6 person.sayHello();
上述代码中,咱们第1行先引入“person.js”模块文件,并存入本地的Person对象中。
第3行,实例化这个Person对象,将实例存入本地的person对象中。
第4-5行,为这个person对象赋值name和url参数。
第6行,访问person对象的sayHello()函数,输出结果。
Ps:到此为止,是否是以为这个东西跟类和对象太类似了?O(∩_∩)O哈哈~
服务器的模块放在那里?
也许你已经注意到,咱们以前在“Node.js 教程 03 - 建立HTTP服务器”中已经在代码中使用了模块了。像这样:
1 var http = require("http"); 2 ... 3 http.createServer(function(){});
Node.js中自带了一个叫作"http"的模块,咱们在咱们的代码中请求它并把返回值赋给一个本地变量。
这把咱们的本地变量变成了一个拥有全部 http 模块所提供的公共方法的对象。
Node.js 的 require方法中的文件查找策略以下:
因为Node.js中存在4类模块(原生模块和3种文件模块),尽管require方法极其简单,可是内部的加载倒是十分复杂的,其加载优先级也各自不一样。以下图所示:
从文件模块缓存中加载
尽管原生模块与文件模块的优先级不一样,可是都不会优先于从文件模块的缓存中加载已经存在的模块。
从原生模块加载
原生模块的优先级仅次于文件模块缓存的优先级。
require方法在解析文件名以后,优先检查模块是否在原生模块列表中。
以http模块为例,尽管在目录 下存在一个http/http.js/http.node/http.json文件,require("http")都不会从这些文件中加载,而是从原生 模块中加载。
原生模块也有一个缓存区,一样也是优先从缓存区加载。若是缓存区没有被加载过,则调用原生模块的加载方式进行加载和执行。
从文件加载
当文件模块缓存中不存在,并且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件。
加载过程当中的包装和编译细节在前一节中已经介绍过,这里咱们将详细描述查找文件模块的过程,其中,也有一些细节值得知晓。
require方法接受如下几种参数的传递: