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

    Node应用由模块组成,采用CommonJS模块规范。

    根据这个规范,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

    CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

    var x = 5;
    var addX = function (value) {
      return value + x;
    };
    module.exports.x = x;
    module.exports.addX = addX;

    上面代码通过module.exports输出变量x和函数addX。

    require方法用于加载模块。

    var example = require('./example.js');
    
    console.log(example.x); // 5
    console.log(example.addX(1)); // 6

    加载:require

    语法:

    var 自定义变量名称 = require('模块')

    作用:

    1、执行被加载模块中的代码

    2、得到被加载模块中的exports导出接口对象

    导出:exports

    Node中是模块作用域,默认文件中所有的成员只在当前文件模块有效。

    对于希望可以被其它模块访问的成员,我们就需要把这些公开的成员都挂载到exports接口对象中就可以了。

    1. 导出多个成员(必须在对象中)

    //foo.js
    var foo = 'bar'
    function add(x, y) {
      return x + y
    }
    exports.foo = foo 
    exports.a = "科比"
    exports.b= "詹姆斯"
    exports.c = add 
    
    //main.js 
    var fooExports = require('./foo')
    console.log(fooExports)
    
    //结果
    { foo: 'bar', a: '科比', b: '詹姆斯', c: [Function: add] }

    2. 导出单个成员

    错误写法1

    //foo.js
    var foo = 'bar'
    
    function add(x, y) {
      return x + y
    }
    exports = foo 
    exports.a = "科比"
    exports.b= "詹姆斯"
    exports.c = add 
    
    //main.js 
    var fooExports = require('./foo')
    console.log(fooExports)
    
    结果为空对象 {}

    错误写法2

    //foo.js
    var foo = 'bar'
    
    function add(x, y) {
      return x + y
    }
    
    exports.a = "科比"
    exports.b= "詹姆斯"
    exports.c = add 
    exports = foo 
    
    //main.js 
    var fooExports = require('./foo')
    console.log(fooExports)
    
    结果为{ a: '科比', b: '詹姆斯', c: [Function: add] }

    如果一个模块需要直接导出某个成员,而非挂载的方式,那这个时候必须使用下面这种方式

    //foo.js
    var foo = 'bar'
    
    function add(x, y) {
      return x + y
    }
    module.exports = foo  //位置一
    exports.a = "科比"
    exports.b= "詹姆斯"
    exports.c = add 
    //module.exports = foo  位置二
    
    /* module.exports = {  位置三
      add: function () {
        return x + y
      },
      str: 'hello'
    } */
    
    //main.js
    var fooExports = require('./foo')
    console.log(fooExports)

    结果:

    只有一个module.exports时,不管是在位置一还是位置二,都为 bar。

    当有两个module.exports 时,比如一个在位置一,另一个在位置三,会导出位置三的对象(module.exports会被后者覆盖)。

    上面的结果出现的原因:exports 和module.exports是有区别的。

    在Node中,每个模块内部都有一个自己的module 对象,该 module 对象中,有一个成员叫exports也是一个对象,类似这样:

    var module = {
      exports: {
        foo: 'bar',
        add: function
      }
    }

    每次导出的对象是module.exports,如果你需要对外导出成员,只需要把导出的成员挂载到module.exports中。

    也就是说module.exports才是真正的接口,exports只不过是它的一个辅助工具。最终返回给调用的是module.exports而不是exports。

    为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令:

    var exports = module.exports

    exports相当于是 一个引用,指向module.exports对象,所以有

    console.log(module.exports === exports)   ///true 

    于是我们可以直接在 exports 对象上添加方法,表示对外输出的接口,如同在module.exports上添加一样。注意,不能直接将exports变量指向一个值,因为这样等于切断了exports与module.exports的联系。

    同理,给 module.exports 重新赋值也会断开。

    但是这里又重新建立两者的引用关系:

    exports = module.exports

    最后,一定要记得return的是module.exports

    如果给exports赋值,断开了两个引用之间的联系,就不管用了。

    module.exports.foo = 'bar'
     exports.a = 'abc'
     exports = {}
     exports.b = '123'  //断开连接后,就没联系了,需重新联系起来
     exports = module.exports
     exports.foo = 'haha'
     module.exports.a = 'cba' 
    
    结果  { foo: 'haha', a: 'cba' }

    exports 和 module.exports 的使用

    如果要对外暴露属性或方法,就用 exports 就行,要暴露对象(类似class,包含了很多属性和方法),就用 module.exports。

  • 相关阅读:
    27. Remove Element
    列表变成字典
    1. Two Sum
    CVPR2019:What and How Well You Performed? A Multitask Learning Approach to Action Quality Assessment
    959. Regions Cut By Slashes
    118. Pascal's Triangle
    loj3117 IOI2017 接线 wiring 题解
    题解 NOI2019 序列
    题解 省选联考2020 组合数问题
    题解 Educational Codeforces Round 90 (Rated for Div. 2) (CF1373)
  • 原文地址:https://www.cnblogs.com/samve/p/10804328.html
Copyright © 2011-2022 走看看