zoukankan      html  css  js  c++  java
  • nodejs模块中exports和module.exports的区别

     通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ ,这些核心模块被编译成二进制文件,可以require('模块名')去获取;核心模块具有最高的加载优先级(有模块与核心模块同名时会体现),如:

    var fs=require('fs');
    var http=require('http')

    文件模块访问方式通过require('/文件名.后缀') require('./文件名.后缀') requrie('../文件名.后缀') 去访问,文件后缀可以省略;以"/"开头是以绝对路径去加载,以"./"开头和以"../"开头表示以相对路径加载,而以"./"开头表示同级目录下文件,如:

    var myadd=require('./add');   //本目录下的add.js

     exports和module.exports;提供了外部访问的接口

    (本文讲exports和module.exports,是对外暴露文件,再引用,属于文件模块。核心模块由node写好,直接引用就行)

    讲讲他们的区别

    1、模块导入会缓存,写了多次导入,只会导一次。

     即使导入的路径不一样。它缓存是指实际文件名,并不会因为传入的路径形式不一样而认会是不同的文件

     1 var outputVal  = 0;     //输出值
     2 var increment = 1;    //增量
     3 /* 设置输出值 */
     4 function seOutputVal (val) {
     5     outputVal = val;
     6 }
     7 /* 设置增量 */
     8 function setIncrement(incrementVal){
     9     increment = incrementVal;
    10 }
    11 /* 输出 */
    12 function printNextCount()
    13 {
    14     outputVal += increment;
    15     console.log(outputVal) ;
    16 }
    17 function printOutputVal() {
    18     console.log(outputVal);
    19 }
    20 exports.seOutputVal = seOutputVal;
    21 exports.setIncrement = setIncrement;
    22 module.exports.printNextCount = printNextCount;
     1 /*
     2     一个Node.js文件就是一个模块,这个文件可能是Javascript代码、JSON或者编译过的C/C++扩展。
     3     重要的两个对象:
     4     require是从外部获取模块
     5     exports是把模块接口公开
     6 */
     7 var counter = require('./1_modules_custom_counter');
     8 console.log('第一次调用模块[1_modules_custom_counter]');
     9 counter.seOutputVal(10);               //设置从10开始计数
    10 counter.setIncrement (10);             //设置增量为10
    11 counter.printNextCount();
    12 counter.printNextCount();
    13 counter.printNextCount();
    14 counter.printNextCount();
    15 /*
    16     require多次调用同一模块不会重复加载
    17 */
    18 var counter = require('./1_modules_custom_counter');
    19 console.log('第二次调用模块[1_modules_custom_counter]');
    20 counter.printNextCount();

     2、通过exports和module.exports对外公开的方法都可以访问,但有区别

    module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是module.exports而不是exports。
    所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是module.exports本身不具备任何属性和方法。
    如果,module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。

    我把exports和 module.exports都打印出来看看究竟

     ①  (虽然这样在引入模块时会报错,但这一步能说明问题,后面说原因)

     1 var counter  = 0;
     2 exports.temp  = function(){
     3     counter += 10;
     4     this.printNextCount = function()
     5     {
     6         console.log(counter);
     7     }
     8 }
     9 var isEq = (exports === module.exports);
    10 console.log(exports);
    11 console.log(module.exports);
    12 console.log(isEq);

    结果:

    通过exports导出的方法,会传递给module.exports。二者没区别

     1 var counter  = 0;
     2 module.exports = function(){
     3     counter += 10;
     4     this.printNextCount = function()
     5     {
     6         console.log(counter);
     7     }
     8 }
     9 var isEq = (exports === module.exports);
    10 console.log(exports);
    11 console.log(module.exports);
    12 console.log(isEq);

    结果:

     

    直接传给module.exports,那exports就说明都没有,二者不相等了。

     ③:注意,导入时有点区别。和上面第一大点不一样

     如这里的②

    1  var  Counter = require('./  ');
    2  var  counterObj = new Counter();
    3  counterObj.printNextCount();

     而第一大点可以直接这样:

    1  var counter = require('./1_modules_custom_counter');
    2  console.log('第二次调用模块[1_modules_custom_counter]');
    3  counter.printNextCount();

     就是要new一个对象!

     因为导出的文件中的函数变成了成员方法,所以要new一个对象,再调用成员方法。

     说明①不可行的原因:当我在别的文件调用它时,无论是直接调用,还是new一个对象再调用,都报错!

     所以,要遵循这两点

    1.最好别分别定义module.exports和exports

    2.NodeJs开发者建议导出对象用module.exports,导出多个方法和变量用exports

    3、exports和module.exports覆盖

    直接上代码,看谁留下,谁消失

     1 var counter  = 0;
     2 exports.printNextCount = function()
     3     {
     4     counter+=2;
     5         console.log(counter);
     6     }
     7 module.exports = function(){
     8 counter+=10;
     9 this.printNextCount=function(){
    10 console.log(counter)
    11 }
    12 
    13 }
    14 var isEq = (exports === module.exports);
    15 console.log(exports);
    16 console.log(module.exports);
    17 console.log(isEq);

    想想都知道谁厉害。

    引用该模块:

    ①报错,说明exports的消失了

    1 var counter = require('./test3');
    2 counter.printNextCount();

    ②留下了。

    1 var counter = require('./test3');
    2 var counterObj=new counter()
    3 counterObj.printNextCount();

     结果,输出了它成功导出的对象函数值;前面两个是两个接口收集到的东西,最后exports的被覆盖了

    exports仅仅是module.exports的一个地址引用。nodejs只会导出module.exports的指向,如果exports指向变了,那就仅仅是exports不在指向module.exports,于是不会再被导出

    相当于:a和b指向同一块内存,b是a的地址引用

    1  var a = new Object();//a相当于module.exports
    2  var b = a; //b相当于exports

    覆盖,也就是a已经赋值了,但b又被赋了别的值。这时候,b就是叛变了,就指向了一块新的地址了。

    而模块引用是要用module.exports来引用,所以指向新地址的exports不起作用了。

    文章是学习笔记,如有错误,望指正

  • 相关阅读:
    Windows 环境 cygwin 安装 SSH
    看见上帝的 10 个公式……
    移动平均
    分位数
    算术平均、几何平均、调和平均、平方平均和移动平均
    平均数、中位数和众数及它们之间的关系
    10 个超炫绘制图表图形的 Javascript 插件【转载+整理】
    “服务器推”技术【转载+整理】
    网站数据监控监测系统
    Active Directory 域服务(AD DS)
  • 原文地址:https://www.cnblogs.com/ooooevan/p/5897586.html
Copyright © 2011-2022 走看看