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。

node.js模块中exports和module.exports的区别的更多相关文章

  1. (译)Node.js的模块-exports和module.exports

    原文标题:Node.js Module – exports vs module.exports 原文链接:http://www.hacksparrow.com/node-js-exports-vs-m ...

  2. Node.js 模块系统入门

    在编程领域中,模块是自包含的功能单元,可以跨项目共享和重用.它们使开发人员的生活更加轻松,因为我们可以使用它来增加应用程序的功能,而不必亲自编写这些功能.它还让我们可以组织和解耦代码,从而使应用程序更 ...

  3. Developer - 如何自我保证Node.js模块质量

    组里正在做SaaS产品,其中一些模块(Module)是Node.js实现,这里我们主要使用Node.js实现Web Server来提供服务. 在做SaaS项目之前,组里的开发模式是传统的Deverlo ...

  4. Node.js中exports与module.exports的区别

    原文:http://www.hacksparrow.com/node-js-exports-vs-module-exports.html 你肯定对Node.js模块中用来创建函数的exports对象很 ...

  5. Node.js模块导出module.exports 和 exports,Es6模块导出export 和export default的区别

    1.module.exports  module变量代表当前模块.这个变量是一个对象,module对象会创建一个叫exports的属性,这个属性的默认值是一个空的对象: module.exports ...

  6. node.js中的exports和module.exports

    不同的编程语言都有各自的代码组织和复用的方式,如.net.php中的命名空间,python中的import,ruby中的module等,来避免命名空间污染.一直都没搞清楚node中的exports和m ...

  7. Node.js中exports,module.exports以及require方法

    在Node.js中,使用module.exports.f = ...与使用exports.f = ...是一样的,此时exports就是module.exports的一种简写方式.但是,需要注意的是, ...

  8. Node.js模块导出exports 和 module.exports 的区别

    原文: https://blog.csdn.net/Pwiling/article/details/51958693 每一个node.js执行文件,都自动创建一个module对象,同时,module对 ...

  9. Node.js中的exports与module.exports的区分

    1. module应该是require方法中,上下文中的对象 2. exports对象应该是上下文中引用module.exports的新对象 3. exports.a = xxx 会将修改更新到mod ...

随机推荐

  1. Prometheus存储模型分析

    Prometheus是时下最为流行的开源监控解决方案,我们可以很轻松地以Prometheus为核心快速构建一套包含监控指标的抓取,存储,查询以及告警的完整监控系统.单个的Prometheus实例就能实 ...

  2. Day03:数组 、 继承的意义(上)

    继承 面向对象编程三(四)大特征 (抽象),封装,继承,多态什么是继承? 继承是面向对象编程中一种代码复用的方式为什么需要继承? 减少代码冗余,提高程序的可维护性和可扩展性怎样使用继承? 语法: cl ...

  3. 接口自动化-python unittest+requests+HTMLrunner

    从2015年毕业入行软件测试,快满4年了,之前技术分享都在百度贴吧上面,现在正式开始在博客中记录工作技术,努力成长,加油 接口测试的步骤1.组装好该接口需要的参数数据2.使用get或post附带参数数 ...

  4. HCL试验3

    PC端配置:配置ip地址 配置网关 交换机(左)配置:①创建VLAN system-view vlan 10 vlan 20 ②配置PC端接口 interface gi 1/0/1 port link ...

  5. Synchronized及其实现原理(一)

    一.Synchronized的基本使用 Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法.Synchronized的作用主要有三个:(1)确保线程互斥的访问同步 ...

  6. 交换机安全学习笔记 第六章 IPV4 ARP攻击

    ARP欺骗攻击 常用工具:  dsniff(Linux/windows).ettercap(Linux/windows).cain(仅windows). ARP欺骗攻击的目的是嗅探发往某主机的所有IP ...

  7. Spring Cloud 使用Feign调用服务传递Header中的参数

    1.使用Feign 调用其他微服务,尤其是在多级调用的同时,需要将一些共同的参数传递至下一个服务,如:token.比较方便的做法是放在请求头中,在Feign调用的同时自动将参数放到restTempla ...

  8. 多次NameNode执行format后DataNode启动不了解决方案

    1.问题 执行start-dfs.sh后在进程中查看jps,发现NameNode启动,但DataNode没有 2.原因 在失败的.log文件中看到datanode的clusterID 和 nameno ...

  9. selenium谷歌火狐插件安装

    1.首先ctrl+r进入终端输入(pip install selenium)进行python安装selenium2.打开百度浏览器进行分别输入geckodriver和Chromedriver对火狐和谷 ...

  10. 10分钟,让你彻底明白Promise原理

    什么是Promise?本代码用定外卖来举例子,让你明白. // 定外卖就是一个Promise,Promist的意思就是承诺// 我们定完外卖,饭不会立即到我们手中// 这时候我们和商家就要达成一个承诺 ...