Node.js 教程 04 - 模块系统
前言:
Node.js的模块系统类似于C/C++的文件引用,可以声明对象,也可以定义类 创建对象。
大家这么理解,就简单了。
定义:
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js应用程序的基本组成部分,文件和模块是一一对应的。
换言之,一个Node.js文件就是一个模块,这个文件可能是Javascript代码、JSON或者编译过的C/C++扩展。
实例一:
这个实例演示的是,在hello.js中创建一个方法,然后在主程序main.js中调用这个方法。
在Node.js中,创建一个模块非常简单,大家跟着做一下就OK了。步骤如下:
步骤1:在E:\NodejsDemo文件夹中,创建一个“hello.js”文件,代码如下:
exports.welcome = function(){
console.log("Welcome to My Blog!");
}
上述代码中,我们使用exports对象,把welcome作为当前hello.js模块的访问接口。
这样,在其他的模块(js文件)中,使用require命令,引入当前js文件,即可直接访问welcome了。
步骤2:同目录下,我们创建一个“main.js”文件,作为要执行的主程序,引入hello.js文件,执行welcome方法,代码如下:
var Hello = require('./hello'); // 引入hello.js模块(文件)
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。
- hello.js中的声明 - exports.welcome = function(){...}
- main.js中的第一句话 - 引入hello.js:var Hello = require('./hello');
require命令我们在之前“Node.js 教程 02 - 经典的Hello World”已经接触过了。
Node.js 提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。
有没有感觉,这个例子很像Java/.NET中的定义类、声明对象、调用方法?
实例二:
Js大牛们知道,在Javascript中,我们可以“定义类、实例化对象”。
那我们如果想把一个对象封装到模块中,应该怎么办呢?
按照上面的实例一,我们照葫芦画瓢:定义一个person类,引入实例化,并赋值,最后调用函数。
步骤1:创建一个“person.js”文件,作为要引入的模块文件,代码如下:
function Person(){
var name;
this.setName = function(_name){
name = _name;
}
var url;
this.setUrl = function(_url){
url = _url;
}
this.sayHello = function(){
console.log("Welcome to my blog!\n" + url);
console.log("My name is " + name +". Nice to meet you!");
}
}
module.exports = Person;
上述代码中,我们创建了一个Person对象,包含两个需赋值参数及一个输出函数。
重点是最后一句: module.exports = Person;
模块接口的唯一变化是使用 module.exports = Person 代替了 exports.world = function(){} 。
在外部引用该模块时,其接口对象就是要输出的 Person 对象本身,而不是原先的 exports。
步骤2:创建主程序“main.js”,引入person.js模块,实例初始化并调用,代码如下:
var Person = require('./person');
var person = new Person();
person.setName("GuYing");
person.setUrl("http://www.cnblogs.com/LonelyShadow");
person.sayHello();
上述代码中,我们第1行先引入“person.js”模块文件,并存入本地的Person对象中。
第3行,实例化这个Person对象,将实例存入本地的person对象中。
第4-5行,为这个person对象赋值name和url参数。
第6行,访问person对象的sayHello()函数,输出结果。
Ps:到此为止,是不是觉得这个东西跟类和对象太相似了?O(∩_∩)O哈哈~
服务器的模块放在那里?
也许你已经注意到,我们之前在“Node.js 教程 03 - 创建HTTP服务器”中已经在代码中使用了模块了。像这样:
var http = require("http");
...
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方法接受以下几种参数的传递:
- http、fs、path等,原生模块。
- ./mod或../mod,相对路径的文件模块。
- /pathtomodule/mod,绝对路径的文件模块。
- mod,非原生模块的文件模块。
Node.js 教程 04 - 模块系统的更多相关文章
- Node.js 教程 01 - 简介、安装及配置
系列目录: Node.js 教程 01 - 简介.安装及配置 Node.js 教程 02 - 经典的Hello World Node.js 教程 03 - 创建HTTP服务器 Node.js 教程 0 ...
- [转载]Node入门 » 一本全面的Node.js教程
http://www.nodebeginner.org/index-zh-cn.html 作者: Manuel Kiessling 翻译: goddyzhao & GrayZhang & ...
- 利用Node.js的Net模块实现一个命令行多人聊天室
1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...
- Node.js的Formidable模块的使用
今天总结了下Node.js的Formidable模块的使用,下面做一些简要的说明. 1) 创建Formidable.IncomingForm对象 var form = new formidab ...
- Node.js入门:模块机制
CommonJS规范 早在Netscape诞生不久后,JavaScript就一直在探索本地编程的路,Rhino是其代表产物.无奈那时服务端JavaScript走的路均是参考众多服务器端语言来 ...
- node.js使用mysql模块的坑
之前用node.js写的订餐系统,很容易挂掉,一直也没想去解决它.今天看了一下,试了试,原因是在连接数据库的时候没有对error事件进行处理,导致程序一直挂在那里,需要重启服务才能正常使用. ...
- [整理]Node入门 » 一本全面的Node.js教程 - Demo实践所遇到的问题
花了一个上午看完[转载]Node入门 » 一本全面的Node.js教程 根据里面的Demo自己手动实现过程中还是遇到了些问题,特整理在此. <1>.由于node.msi安装包已经自动添加了 ...
- 【转载】Node.js 教程(菜鸟教程系列)
很好的一篇教程:Node.js 教程 简单做下笔记 概述 简单的说 Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrome JavaScript 运行时建立 ...
- 实用的 Node.js 教程,工具和资源
这里分享一批实用的实用的 Node.js 教程,工具和资源. Node.js是一个建立在Chrome之上的JavaScript运行时平台,可方便地构建快速,可扩展的网络应用程序.Node.js使用事件 ...
随机推荐
- 死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?
写在前面 阅读目录: 设计误区 数据库已死 枚举映射 关联映射 后记 在上一篇<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>博文中, ...
- ABP框架 - 会话
文档目录 本节内容: 简介 关于 IAbpSeesion 注入会话 会话属性 用户标识符 简介 如果一个应用需要登录,它就需要知道当前用户在执行的操作.尽管Asp.net自身在展现层提供了Sessio ...
- 菜鸟学Struts2——HelloWorld
写在前面 自从工作后就过上了只有一个月记忆的生活,太健忘,很多学过的东西因为用得少便忘记了,第二次学习struts,为了以后便于查阅,开始自己的博客之旅.Struts的学习还是从Hello World ...
- 日向blog开发记录
一点历史关于,Sonne Blog 2016.03.25springmvc + hibernate框架搭建.2016.04.21日向blog首页.2016.04.24分页实现.2016.04.30登录 ...
- [转]Python中的str与unicode处理方法
早上被python的编码搞得抓耳挠腮,在搜资料的时候感觉这篇博文很不错,所以收藏在此. python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...
- Javascript之函数模型
分析: 对于js自定义函数,函数体的内容大致可抽象为:变量(局部变量,由var关键字定义,全局变量)和函数(一般函数,匿名函数,闭包函数). function SelfDefineFunc() { v ...
- VR ( Virtual Reality )、AR(Augmented Reality)、MR(Mix Reality)和CR(Cinematic Reality)是什么鬼?
整个社会对虚拟现实的研究和开发源于上个世纪六十年代,计算机图形学.人机接口技术.图像处理与模式识别.多传感技术.语音处理与音响技术.高性能计算机系统.人工智能等领域在之后半个世纪取得了长足的发展为虚拟 ...
- Java关键字:static
通常,当创建类时,就是在描述那个类的外观和行为.只有用new创建类的对象时,才分配数据存储空间,方法才能被调用.但往往我们会有下面两种需求: 1.我想要这样一个存储空间:不管创建多少对象,无论是不创建 ...
- c#文件操作
1.创建文件夹 //using System.IO; Directory.CreateDirectory(%%1); 2.创建文件 //using System.IO; File.Create(% ...
- H5拍照应用开发经历的那些坑儿
一.项目简介 1.1.项目背景:这是一个在移动终端创新应用的项目,用户在浏览器端(微信/手Q)即可完成与金秀贤的合影,希望通过这样一种趣味体验,引发用户的分享与转发的热潮. 1.2.系统要求:ios6 ...