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


Posted in NodeJs onMay 25, 2014

简介及资料

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

创建一个自定义模块

 

以一个计数器为例

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

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;提供了外部访问的接口,下面调用一下看看效果吧

调用自定义模块

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

/*
    一个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对外公开的方法都可以访问!那既然两种都能达到效果,但总得有点区别的吧~~~用个例子看看吧!

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

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文件调用一下

跟我学Nodejs(三)--- Node.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();

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

    调用后,执行结果如上图

    我在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,结果如何?

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

调用结果

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

    从结果可以看出,并没有报错,表示可以这么定义,但最终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

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

NodeJs 相关文章推荐
轻松创建nodejs服务器(1):一个简单nodejs服务器例子
Dec 18 NodeJs
NodeJS使用jQuery选择器操作DOM
Feb 13 NodeJs
iPhone手机上搭建nodejs服务器步骤方法
Jul 06 NodeJs
nodejs微信公众号支付开发
Sep 19 NodeJs
Nodejs多站点切换Htpps协议详解及简单实例
Feb 23 NodeJs
angular2+nodejs实现图片上传功能
Mar 27 NodeJs
nodejs批量下载图片的实现方法
May 19 NodeJs
mac下的nodejs环境安装的步骤
May 24 NodeJs
详解IWinter 一个路由转控制器的 Nodejs 库
Nov 15 NodeJs
nodejs更改项目端口号的方法
May 13 NodeJs
Nodejs使用Mongodb存储与提供后端CRD服务详解
Sep 04 NodeJs
nodejs中express入门和基础知识点学习
Sep 13 NodeJs
跟我学Nodejs(二)--- Node.js事件模块
May 21 #NodeJs
跟我学Nodejs(一)--- Node.js简介及安装开发环境
May 20 #NodeJs
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
Mar 18 #NodeJs
用nodejs实现PHP的print_r函数代码
Mar 14 #NodeJs
nodejs读取memcache示例分享
Jan 02 #NodeJs
利用NodeJS和PhantomJS抓取网站页面信息以及网站截图
Nov 18 #NodeJs
NodeJS的url截取模块url-extract的使用实例
Nov 18 #NodeJs
You might like
phpexcel导入excel数据使用方法实例
2013/12/24 PHP
分享一则PHP定义函数代码
2015/02/26 PHP
php使用ftp远程上传文件类(完美解决主从文件同步问题的方法)
2016/09/23 PHP
Yii2 hasOne(), hasMany() 实现三表关联的方法(两种)
2017/02/15 PHP
IE8 浏览器Cookie的处理
2009/01/31 Javascript
30分钟就入门的正则表达式基础教程
2013/02/25 Javascript
在js文件中如何获取basePath处理js路径问题
2013/07/10 Javascript
angularjs中的单元测试实例
2014/12/06 Javascript
JavaScript实现快速排序的方法
2015/07/31 Javascript
requireJS使用指南
2016/04/27 Javascript
jQuery实现页面下拉100像素出现悬浮窗口的方法
2016/09/05 Javascript
bootstrap与Jquery UI 按钮样式冲突的解决办法
2016/09/23 Javascript
详解微信小程序 wx.uploadFile 的编码坑
2017/01/23 Javascript
js实现文本上下来回滚动
2017/02/03 Javascript
关于Node.js中Buffer的一些你可能不知道的用法
2017/03/28 Javascript
vue子组件改变父组件传递的prop值通过sync实现数据双向绑定(DEMO)
2020/02/01 Javascript
[01:10]3.19DOTA2发布会 三代刀塔人第一代
2014/03/25 DOTA
深入浅析python继承问题
2016/05/29 Python
利用python模拟sql语句对员工表格进行增删改查
2017/07/05 Python
Python模拟鼠标点击实现方法(将通过实例自动化模拟在360浏览器中自动搜索python)
2017/08/23 Python
Python3 Random模块代码详解
2017/12/04 Python
利用python为运维人员写一个监控脚本
2018/03/25 Python
python3使用SMTP发送HTML格式邮件
2018/06/19 Python
python os.path模块常用方法实例详解
2018/09/16 Python
python 自动重连wifi windows的方法
2018/12/18 Python
Python如何使用turtle库绘制图形
2020/02/26 Python
英国家庭珠宝商:T. H. Baker
2018/02/08 全球购物
英国在线照明超市:Castlegate Lights
2019/10/30 全球购物
灵泰克Java笔试题
2016/01/09 面试题
教师的实习自我鉴定
2013/12/17 职场文书
霸王洗发水广告词
2014/03/14 职场文书
分公司经理任命书
2014/06/05 职场文书
爱与责任师德演讲稿
2014/08/26 职场文书
狂人日记读书笔记
2015/06/30 职场文书
Python进度条的使用
2021/05/17 Python
vue的项目如何打包上线
2022/04/13 Vue.js