• module.exports和exports


      首先要认识module.exports和exports分别是什么。

      在nodejs中,提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。但exports是引用 module.exports的值。module.exports 被改变的时候,exports不会被改变,而模块导出的时候,真正导出的执行是module.exports,而不是exports。

      每一个node.js执行文件,都自动创建一个module对象,同时,module对象会创建一个叫exports的属性,初始化的值是 {}

     module.exports = {};

      关于这两个的知识点,目前了解的主要在两个方面:

      第一个就是在exports抛出的接口中,如果你希望你的模块就想为一个特别的对象类型,请使用module.exports;如果希望模块成为一个传统的模块实例,请使用exports.xx方法;module.exports才是真正的接口,exports只不过是它的一个辅助工具。最终返回给调用的是module.exports而不是exports。也就是构造函数必须使用module.exports。如下面案例:

    新建一个time.js:

    module.exports=function(year,month,day){
            this.year=year;
            this.month=month;
            this.day=money;
            this.say=function(){
                    console.log('今天是:'+this.year+',年'+this.month+'月,月薪为:'+this.day+'日;')
            }
    };

    这里的module.exports被赋予了一个构造函数;再新建一个main.js,其中引入time.js这个模块,把exports方法接受进来,main.js代码如下:

    var Hello=require('./time');
    var hello=new Hello('2017','9','27')
    hello.say();

    进入node环境,运行main.js,可以看到,已经打印出来:


    而在time.js中,我们是赋予了exports一个函数 ,当然,也可以采用匿名函数的方式;见代码:

    function hello(year,month,day){
            this.year=year;
            this.month=month;
            this.day=day;
            this.say=function(){
                    console.log('今天是:'+this.year+'年'+this.month+'月,'+this.day+'日;')
            }
    }
    
    module.exports=hello;

    以上modle.exports,这个模块很明显是一个特别的对象模型;那如果采用对象实例的方法该如何实现呢?其实也很简单,只需要给exports对象负值一个新的方法即可;见下面代码:

    function hello(year,month,day){
            this.year=year;
            this.month=month;
            this.day=day;
            this.say=function(){
                    console.log('今天是:'+this.year+'年'+this.month+'月,'+this.day+'日;')
            }
    }
    var Hello = new hello('2017','9','27')
    exports.add = Hello;

    这时候用的就是exports了

    在time.js中,依然是一个构造函数,声明了一个变量Hello,然后再把Hello赋值给exports自定义的add方法;那么在main.js中,由于add已经是exports的一个自定义的实例方法了,因此我们可以直接这么调用它:Hello.add.say();见代码:

    var Hello=require('./time');
    Hello.add.say()

    输出一样,结束。

    第二个:

      首先来看下这个问题:

      

    test.js

    var a = {name: 1};
    var b = a;
    
    console.log(a);
    console.log(b);
    
    b.name = 2;
    console.log(a);
    console.log(b);
    
    var b = {name: 3};
    console.log(a);
    console.log(b);
    

    运行 test.js 结果为:

    { name: 1 }
    { name: 1 }
    { name: 2 }
    { name: 2 }
    { name: 2 }
    { name: 3 }
    

    解释:a 是一个对象,b 是对 a 的引用,即 a 和 b 指向同一块内存,所以前两个输出一样。当对 b 作修改时,即 a 和 b 指向同一块内存地址的内容发生了改变,所以 a 也会体现出来,所以第三四个输出一样。当 b 被覆盖时,b 指向了一块新的内存,a 还是指向原来的内存,所以最后两个输出不一样。是不是和Java也有点像。

    明白了上述例子后,我们只需知道三点就知道 exports 和 module.exports 的区别了:

    1. module.exports 初始值为一个空对象 {}
    2. exports 是指向的 module.exports 的引用
    3. require() 返回的是 module.exports 而不是 exports

    我们可以这样:

    exports = module.exports = {...}

    经常看到这样的写法:

    exports = module.exports = {...}
    

    上面的代码等价于:

    module.exports = {...}
    exports = module.exports
    

    原理很简单:module.exports 指向新的对象时,exports 断开了与 module.exports 的引用,那么通过 exports = module.exports 让 exports 重新指向 module.exports。

    继续看一个例子:

    foo.js

     exports.a = function(){
     console.log('a')
     }
    
     exports.a = 1

    test.js

     var x = require('./foo');
    
     console.log(x.a)

    看到这里,相信大家都看到答案了,exports是引用 module.exports的值。module.exports 被改变的时候,exports不会被改变,而模块导出的时候,真正导出的执行是module.exports,而不是exports

    再看看下面例子

    foo.js

     exports.a = function(){
      console.log('a')
     }
    
     module.exports = {a: 2}
     exports.a = 1

    test.js

     var x = require('./foo');
    
     console.log(x.a)

    result:

     2

    exports在module.exports 被改变后,失效。

    javascript里面有一句话,函数即对象,View 是对象,module.export =View, 即相当于导出整个view对象。外面模块调用它的时候,能够调用View的所有方法。不过需要注意,只有是View的静态方法的时候,才能够被调用,prototype创建的方法,则属于View的私有方法。

    foo.js

     function View(){
    
     }
    
     View.prototype.test = function(){
      console.log('test')
     }
    
     View.test1 = function(){
      console.log('test1')
     }

    module.exports = View

    test.js

     var x = require('./foo');
    
     console.log(x) //{ [Function: View] test1: [Function] }
     console.log(x.test) //undefined
     console.log(x.test1) //[Function]
     x.test1() //test1

    ##var app = exports = module.exports = {};

    其实,当我们了解到原理后,不难明白这样的写法有点冗余,其实是为了保证,模块的初始化环境是干净的。同时也方便我们,即使改变了 module.exports 指向的对象后,依然能沿用 exports的特性

     exports = module.exports = createApplication;
    
     /**
      * Expose mime.
      */
    
     exports.mime = connect.mime;

    例子,当中module.exports = createApplication改变了module.exports了,让exports失效,通过exports = module.exports的方法,让其恢复原来的特点。

    ##exports.init= function(){}

    这种最简单,直接就是导出模块 init的方法。

    ##var mongoose = module.exports = exports = new Mongoose;

    集多功能一身的写法

  • 相关阅读:
    消息中间件 kafka rabbitmq 选型差异
    kafka生产部署
    logback不同业务的日志打印到不同文件
    Java并发编程核心概念一览
    大数据分析常用去重算法分析『Bitmap 篇』
    java 堆调优
    大规模使用 Apache Kafka 的20个最佳实践
    es定期删除数据
    HTTP协议中源端口和目标端口的问题
    How to duplicate the records in a MongoDB collection
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/7603374.html
Copyright © 2020-2023  润新知