• 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。

  • 相关阅读:
    剑指63.数据流中的中位数
    剑指62.二叉搜索树的第k个结点
    JPA ---- EntityManager使用
    JPA ---- EntityManager介绍
    win10多桌面切换
    $emit子组件如何传递多个参数
    height高度自适应
    vue Avoided redundant navigation to current location
    Ant Design 使用小结
    Object.keys方法之详解
  • 原文地址:https://www.cnblogs.com/samve/p/10804328.html
Copyright © 2020-2023  润新知