通过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、模块导入会缓存,写了多次导入,只会导一次。

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

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

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

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

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

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

 var counter  = 0;
exports.temp = function(){
counter += 10;
this.printNextCount = function()
{
console.log(counter);
}
}
var isEq = (exports === module.exports);
console.log(exports);
console.log(module.exports);
console.log(isEq);

结果:

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

 var counter  = 0;
module.exports = function(){
counter += 10;
this.printNextCount = function()
{
console.log(counter);
}
}
var isEq = (exports === module.exports);
console.log(exports);
console.log(module.exports);
console.log(isEq);

结果:

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

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

如这里的②

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

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

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

就是要new一个对象!

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

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

所以,要遵循这两点

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

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

3、exports和module.exports覆盖

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

 var counter  = 0;
exports.printNextCount = function()
{
counter+=2;
console.log(counter);
}
module.exports = function(){
counter+=10;
this.printNextCount=function(){
console.log(counter)
} }
var isEq = (exports === module.exports);
console.log(exports);
console.log(module.exports);
console.log(isEq);

想想都知道谁厉害。

引用该模块:

①报错,说明exports的消失了

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

②留下了。

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

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

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

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

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

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

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

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

nodejs模块中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. nodejs中exports与module.exports的区别

    转自--http://www.cnblogs.com/pigtail/archive/2013/01/14/2859555.html 你肯定非常熟悉nodejs模块中的exports对象,你可以用它创 ...

  3. nodeJS实战:自定义模块与引入,不同模块的函数传递及回调处理,exports与module.exports(基于nodejs6.2.0)

    前言:本文基于上一篇文章中的源代码进行改写,地址:http://blog.csdn.net/eguid_1/article/details/52182386 注意:为什么不用module.export ...

  4. nodeJS学习(9)--- nodeJS模块:exports vs module.exports

    模块简介: 通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ 这些核心模块被编译成二进制文件,可以 require('模块名') ...

  5. nodejs中exports与module.exports的区别详细介绍

    如果模块是一个特定的类型就用Module.exports.如果模块是一个典型的"实例化对象"就用exports. exports.name = function() { conso ...

  6. node.js模块中exports和module.exports的区别

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

  7. nodejs中的exports和module.exports

    module是随文件而生的全局变量,它有exports属性,这个属性默认是一个空的字典. node的设计者画蛇添足有定义了一个exports全局变量,export指向module.exports所指向 ...

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

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

  9. 理解node模块的exports和module.exports

    exports是module.exports的引用,即var exports = module.exports.在一个模块的开头,这两个值都指向同一个空对象:exports = module.expo ...

随机推荐

  1. 理解CSS视觉格式化

    前面的话   CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应 ...

  2. HTML kbd键盘元素

    1. 说明 kbd :即Keyboard Input Element(键盘输入元素).表示键盘按键的语义元素,常用于网页上对快捷键.按键说明的场景. 样式规格:内联样式. 为了在页面上突出显示,可以给 ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(67)-MVC与ECharts

    系列目录 ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Fire ...

  4. springMVC学习笔记--知识点总结1

    以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...

  5. PHP与JAVA构造函数的区别

    早期的PHP是没有面向对象功能的,但是随着PHP发展,从PHP4开始,也加入了面向对象.PHP的面向对象语法是从JAVA演化而来,很多地方类似,但是又发展出自己的特色.以构造函数来说,PHP4中与类同 ...

  6. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

  7. .NET同步与异步之相关背景知识(六)

    在之前的五篇随笔中,已经介绍了.NET 类库中实现并行的常见方式及其基本用法,当然.这些基本用法远远不能覆盖所有,也只能作为一个引子出现在这里.以下是前五篇随笔的目录: .NET 同步与异步之封装成T ...

  8. RabbitMQ + PHP (二)AMQP拓展安装

    上篇说到了 RabbitMQ 的安装. 这次要在讲案例之前,需要安装PHP的AMQP扩展.不然可能会报以下两个错误. 1.Fatal error: Class 'AMQPConnection' not ...

  9. css样式之background详解

    background用法详解: 1.background-color 属性设置元素的背景颜色 可能的值 color_name            规定颜色值为颜色名称的背景颜色(比如 red) he ...

  10. android Notification介绍

    如果要添加一个Notification,可以按照以下几个步骤 1:获取NotificationManager: NotificationManager m_NotificationManager=(N ...