设为首页 收藏本站
查看: 1212|回复: 0

[经验分享] Nodejs学习笔记(三)--- 模块

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2017-2-22 11:08:40 | 显示全部楼层 |阅读模式
目录




  • 简介及资料
  • 自定义模块

    • 创建一个自定义模块
    • 调用自定义模块
    • exports和module.exports 区别
    • exports和module.exports 覆盖
    • 其它...



简介及资料

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


创建一个自定义模块
  以一个计数器为例
DSC0000.png



DSC0001.gif DSC0002.gif


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


调用自定义模块
DSC0003.png






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






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






var Counter = require('./2_modules_diff_exports');
Counter.printNextCount();
2_modules_diff_exports_load.js 文件源码
  调用后,执行结果如上图
  我在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();
DSC0006.png


  调用后,执行结果如上图
  我在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,结果如何?
DSC0007.png

  调用结果


  从结果可以看出,并没有报错,表示可以这么定义,但最终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
  返回该模块引用的所有模块对象的数组

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345662-1-1.html 上篇帖子: NodeJS开发环境配置 下篇帖子: NodeJS + PhantomJS 抓取页面信息以及截图
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表