跟我学Nodejs(三)--- Node.js模块

简介及资料

通过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

  返回该模块引用的所有模块对象的数组

(0)

相关推荐

  • 用C/C++来实现 Node.js 的模块(一)

    N久之前的一个坑--用 Node.js 来重构 NBUT 的 Online Judge,包括评测端也得重构一遍.(至于什么时候完成大家就不要关心了,(/‵Д′)/~ ╧╧ 总之我们现在要做的其实简而言之就是--用C/C++来实现 Node.js 的模块. 准备工作 工欲善其事,必先~~耍流氓~~利其器. node-gyp 首先你需要一个 node-gyp 模块. 在任意角落,执行: 复制代码 代码如下: $ npm install node-gyp -g 在进行一系列的 blahblah 之后,

  • Node.js模块加载详解

    JavaScript是世界上使用频率最高的编程语言之一,它是Web世界的通用语言,被所有浏览器所使用.JavaScript的诞生要追溯到Netscape那个时代,它的核心内容被仓促的开发出来,用以对抗Microsoft,参与当时白热化的浏览器大战.由于过早的发布,无可避免的造成了它的一些不太好的特性. 尽管它的开发时间很短,但是JavaScript依然具备了很多强大的特性,不过,每个脚本共享一个全局命名空间这个特性除外. 一旦Web页面加载了JavaScript代码,它就会被注入到全局命名空间,

  • Node.js 的模块知识汇总

    在写 Node.js 应用程序的时候,你确实可以把所有代码放在巨大原 index.js 文件中,不在乎你的应用程序会变得多大多复杂.Node.js 解释器不会在意这个事情.但在代码组织方面,你很快就会陷入混乱,不能理解代码,而且难以调试.所以,作为一个人,你应该关心代码的结构.这就是使用模块的原因. 你可以把 Node.js 模块当作 JavaScript 库 -- 是整体代码中你想放在一起的某个部分(比如,函数集),你会想把这部分代码相对独立于代码库中的其它部分,可以把事情区分清楚. 就们我们

  • 跟我学Nodejs(二)--- Node.js事件模块

    简介及资料 http://nodejs.org/api/events.html http://www.infoq.com/cn/articles/tyq-nodejs-event events是node.js 最重要的模块,events模块只提供了一个对象events.EventEmitter,EventEmitter 的核心是事件发射与事件监听器. Node.js中大部分的模块,都继承自Event模块. 与DOM树上事件不同,不存在事件冒泡.逐层捕获等行为. EventEmitter 支持若干

  • node.js使用require()函数加载模块

    详细说明均以写在注释之中,这里就不啰嗦了,小伙伴们自己详细看吧,千万别吧注释当成空气了. 复制代码 代码如下: /*在node中,可以使用require()函数来加载模块.  * require函数使用一个参数,参数值可以带有完整路径的模块的文件名,也可以为模块名.当使用node中提供的模块时,在require函数中只需要指定模块名即可.  * */ //建立一个页面2.js;代码如下 var name="思思博士"; exports.name=name; //建立一个页面1.js;代

  • NODE.JS加密模块CRYPTO常用方法介绍

    使用require('crypto')调用加密模块. 加密模块需要底层系统提供OpenSSL的支持.它提供了一种安全凭证的封装方式,可以用于HTTPS安全网络以及普通HTTP连接. 该模块还提供了一套针对OpenSSL的hash(哈希),hmac(密钥哈希),cipher(编码),decipher(解码),sign(签名)以及verify(验证)等方法的封装. crypto.createCredentials(details) 创建一个凭证对象,可选参数details为一个带键值的字典: key

  • 在Windows上安装Node.js模块的方法

    不过有消息称Microsoft已经联系Node.js官方,相信很快会有改善. 那么在不安装Cygwin的情况下,是否可以在Windows上搭建Node.js环境进行试验开发哪?我以Node.js + express做了个简单测试,基本可行. 步骤如下: 1. 下载Node.js官方非稳定版Windows可执行程序: http://nodejs.org/#download 我在试验中使用了0.5.7版本:http://nodejs.org/dist/v0.5.7/node.exe 2. 创建c:\

  • node.js 模块和其下载资源的镜像设置的方法

    以前安装 electron 时总是失败,然后就在淘宝镜像上下载好相应版本的文件放到用户目录来解决问题. 后来研究发现 npm 不仅可以设置 node.js 模块仓库的代理, 同样可以设置像 electron.phantomjs. node-sass 等模块的镜像代理 一.设置淘宝镜像 (共三种方法) 1.环境变量 Unix: # electron export ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ # phantomjs

  • Node.js模块全局安装路径配置方法

    下载安装NodeJS后,在自己选择的路径下会有如下的文件: 默认情况下NodeJS安装会同时安装npm(模块管理器:用于管理用户require的模块,有全局和本地两种). 注: 全局:执行npm install <模块的名字> -g 就会将模块装在全局路径下,当用户在程序中require(<模块的名字>)的时候不用考虑模块在哪,如果不修改全局路径,用户下载的模块会默认在C:\Users\Administrator\AppData\Roaming\npm这个路径下. 局部:执行npm

  • 详解Node.JS模块 process

    process 模块是 nodejs 提供给开发者用来和当前进程交互的工具,它的提供了很多实用的 API.从文档出发,管中窥豹,进一步认识和学习 process 模块: 如何处理命令参数? 如何处理工作目录? 如何处理异常? 如何处理进程退出? process 的标准流对象 深入理解 process.nextTick 如何处理命令参数? 命令行参数指的是 2 个方面: 传给 node 的参数.例如 node --harmony script.js --version 中,--harmony 就是

  • Node.js模块封装及使用方法

    Node.js中也有一些功能的封装,类似C#的类库,封装成模块这样方便使用,安装之后用require()就能引入调用. 一.Node.js模块封装 1.创建一个名为censorify的文件夹 2.在censorify下创建3个文件censortext.js.package.json.README.md文件 1).在censortext.js下输入一个过滤特定单词并用星号代替的函数. var censoredWorlds=["sad","bad","mad&

  • 快速掌握Node.js模块封装及使用

    Node.js中也有一些功能的封装,类似C#的类库,封装成模块这样方便使用,安装之后用require()就能引入调用. 一.Node.js模块封装 1.创建一个名为censorify的文件夹 2.在censorify下创建3个文件censortext.js.package.json.README.md文件 1).在censortext.js下输入一个过滤特定单词并用星号代替的函数. var censoredWorlds=["sad","bad","mad&

  • 详细分析Node.js 模块系统

    为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统. 模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的.换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码.JSON 或者编译过的C/C++ 扩展. 创建模块 在 Node.js 中,创建一个模块非常简单,如下我们创建一个 main.js 文件,代码如下: var hello = require('./hello'); hello.world(); 以上实例中,代

  • 跟我学Nodejs(三)--- Node.js模块

    简介及资料 通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ ,这些核心模块被编译成二进制文件,可以require('模块名')去获取:核心模块具有最高的加载优先级(有模块与核心模块同名时会体现) (本次主要说自定义模块) Node.js还有一类模块为文件模块,可以是JavaScript代码文件(.js作为文件后缀).也可以是JSON格式文本文件(.json作为文件后缀).还可以是编辑过的C/C++文件(.node作为文件后

  • 学习Node.js模块机制

    一.CommonJS的模块规范 Node与浏览器以及 W3C组织.CommonJS组织.ECMAScript之间的关系 Node借鉴CommonJS的Modules规范实现了一套模块系统,所以先来看看CommonJS的模块规范. CommonJS对模块的定义十分简单,主要分为模块引用.模块定义和模块标识3个部分. 1. 模块引用 模块引用的示例代码如下: var math = require('math'); 在CommonJS规范中,存在require()方法,这个方法接受模块标识,以此引入一

  • 详解Node.js模块间共享数据库连接的方法

    这个标题本身就是一个命题,因为使用默认方式的情况下,一个 Node.js 应用里的各个模块都是共享的同一个数据库连接.但是如果姿势不对,可能会很丑陋,甚至可能会出错. 你可以忽略下面这部分,直接切入正题. 背景 最近在做专业课程设计,题目是"机票预订管理系统".需求比较简单,就试着拿最近在学的 Node.js 来做了.本来还在调研用何种 Node.js 框架比较合适,看了几个框架之后发现这是杀鸡用牛刀,有看文档查资料的时间还不如直接动手写了.最后写完我会把代码放到 Github 上,欢

随机推荐