对module.exports和exports的一些理解

可能是有史以来最简单通俗易懂的有关Module.exports和exports区别的文章了。

exports = module.exports = {};

所以module.exportsexports的区别就是var a={}; var b=a;,a和b的区别

看起来木有什么太大区别,但实际用起来的时候却又有区别,这是为啥呢,请听我细细道来

关于Module.exports和exports有什么区别,网上一搜一大把,但是说的都太复杂了…
听说exports是Module.exports对象的一个引用(reference)^1,什么是引用?!…_(:з」∠)_

当然啦,如果要彻底理解这两个导出的区别,最好肯定是去看源码,看看都是怎么封装的,功力深厚的童鞋应该一看就懂了。不过,源码我也是看不懂的…(ಥ_ಥ)

但是最近感觉杂七杂八看了好多文章做了好多实验之后,像是打开了任督二脉,机智的我好像有点上道了…

module

首先要明确的一点,module是一个对象 {Object}
当你新建一个文件,比如mo.js,文件内容如下:

1
console.log(module);

然后在CMD里执行这个文件node mo.js,就能看到module其实是一个Module实例,你可以这么理解,NodeJS中定义了一个Module类,这个类中有很多属性和方法,exports是其中的一个属性:

1
2
3
4
5
function Module {
id : 'blabla',
exports : {},
blabla...
}

当每个js文件在执行或被require的时候,NodeJS其实创建了一个新的实例var module = new Module(),这个实例名叫module
这也就是为什么你并没有定义module这个变量,却能console.log出来而不会报错的原因

module.exports

假设我有一个JS文件内容如下:

console.log(module); //你会看到Module中的exports为空对象{}
module.exports = {
print : function(){console.log(12345)}
}
console.log(module); //你会看到Module中的exports对象已经有了print()方法

有了上面的基础,很容易理解module.export其实是给Module实例中的exports对象中添加方法/属性

exports

通常使用exports的时候,是这么用的:

exports.print = function(){console.log(12345)}

假设我有一个JS文件内容如下:

console.log(module); //你会看到Module中的exports为空对象{}
console.log(exports); //你会看到Module中的exports为空对象{}
module.exports = {
print : function(){console.log(12345)}
}
console.log(module); //你会看到Module中的exports对象有了print()方法
exports.name = '小白妹妹';
console.log(module); //你会看到Module中的exports对象不仅有了print()方法,还有了name属性

由此也能看出,传说中的exports其实是module.exports的引用,你可以这么理解,NodeJS在你的代码之前悄悄的加了以下代码:

var module = new Module();
var exports = module.exports;

这也就是为什么你并没有定义exports这个变量,却能console.log出来而不会报错的原因

require

当你从外部调用某个模块,require其实是在require什么?^2
require的时候NodeJS会到处去找有没有这个模块,如果有,return的就是module.exports里的东东。

DOs & DONTs

  • √你可以这样:

    module.exports.name = '小白妹妹';
    exports.age = 10;
    module.exports.print = function(){console.log(12345)};

    如果只是使用.来添加属性和方法,module.exportsexports混用是完全可以的,这种情况下,感觉exports就是给懒人用的…毕竟能少写几个7个字符呢!

  • √也可以这样:
    module.exports = {
    name = '小白妹妹';
    };
    exports.age = 10;
    module.exports.print = function(){console.log(12345)};
  • ×但不可以这样
    module.exports = {
    name = '小白妹妹';
    };
    exports = {age:10}; // exports现在是{age:10}这个对象的引用,不再是module.exports的引用了
    console.log(module); //你会看到Module的exports中只有name属性!!!
  • ×也不可以这样
    exports.age = 10;
    console.log(module); //你会看到Module的exports中多了age属性
    module.exports = {
    name = '小白妹妹';
    };
    console.log(module); //你会看到Module的exports中还是只有name属性!!!

    总结

    还是那一句话,module.exportsexports的区别就是var a={}; var b=a;,a和b的区别

    • 改变exports的指向后所添加的exports.xxx都是无效的。因为require返回的只会是module.exports
  • 不能在使用了exports.xxx之后,改变module.exports的指向。因为exports.xxx添加的属性和方法并不存在于module.exports所指向的新对象中。
  • 对于要导出的属性,可以简单直接挂到exports对象上
  • 对于类,为了直接使导出的内容作为类的构造器可以让调用者使用new操作符创建实例对象,应该把构造函数挂到module.exports对象上,不要和导出属性值混在一起

module.exports和exports得区别的更多相关文章

  1. node (02 CommonJs 和 Nodejs 中自定义模块)顺便讲讲module.exports和exports的区别 dependencies 与 devDependencies 之间的区别

    CommonJS 规范的提出,主要是为了弥补当前 JavaScript 没有标准的缺陷.它的终极目标就是:提供一个类似 Python,Ruby 和 Java 语言的标准库,而不只是停留在小脚本程序的阶 ...

  2. module.exports 、exports、export、export default的区别

    module.exports和exports是属于 CommonJS 模块规范,export和export default是属于ES6语法. module.exports和exports导出模块,用r ...

  3. module.exports与exports的联系与区别

    首先说明他们是啥? 在CommonJS规范中,exports和module.exports这两个对象是把某一模块化文件中的属性和方法暴露给外部模块的接口(说法可能不准确),外部模块通过require引 ...

  4. 浅析module.exports和exports区别和使用

    module.exports和exports 写node的时候,特别是自定义模块的时候,都是一顿乱敲,然后module.exports={}完事. 但有时候去看别人写的代码的时候会发现还可以expor ...

  5. Module.exports和exports的区别

    原文链接: https://www.ycjcl.cc/2017/02/10/module-exportshe-exportsde-qu-bie/ 学习Seajs时,看到了exports.doSomet ...

  6. module中module.exports与exports的区别(转)

    转https://cnodejs.org/topic/55ccace5b25bd72150842c0a require 用来加载代码,而 exports 和 module.exports 则用来导出代 ...

  7. NodeJS2-3环境&调试----module.exports与exports的区别

    exports默认会给他设置为module.exports的快捷方式,可以把它的里面添加属性,但是我们不能修改它的指向,如果修改了它的指向那它和普通对象没有任何区别了.因为在CommonJS中,模块对 ...

  8. Node.js module.exports和exports的区别

    require 用来加载代码,而 exports 和 module.exports 则用来导出代码,从接触node.js就不会它们两陌生,上代码: foo.js exports.a = functio ...

  9. Node中Exports与module.export的使用与区别

    最近在看<node开发实战详解>时有写疑问,所以自己就整理了一些资料.下面是node4.*的官方api文档(http://nodejs.cn/doc/node_4/modules.html ...

随机推荐

  1. 关于JSON日期格式显示及My97日期控件

    1.My97日期控件.显示不同的日期格式,可以调整"dateFmt“的参数来配置: 详细DEMO:http://www.my97.net/demo/index.htm <p>日期 ...

  2. vue生成图片验证码

    最近做项目接触Vue,前端生成验证码.原理其实很简单,首先是生成随机数,然后用canvas绘制. 网上有一些现成的资料,没必要重复造轮子,我是在他们基础上完善了父组件,简化了子组件的调用: ident ...

  3. shell基础(三)

    函数 1.可以带function fun() 定义,也可以直接fun() 定义,不带任何参数: 2.参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值: 3.必须 ...

  4. Linux下tomcat相关操作

    tomcat安装: 直接到官网下载tar包解压即可. tomcat相关操作: 首先,进入Tomcat下的bin目录,例如:cd /usr/tomcat/bin 启动Tomcat:./startup.s ...

  5. zoj3497(经典矩阵乘法)

    原以为是用搜索做的题,想了好久都无法想到一个高效正确的解法. 后面发现竟然这就是矩阵的应用! 碉堡! 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值  ——选自ma ...

  6. poj1691

    Painting A Board Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3642   Accepted: 1808 ...

  7. 一个有意思的 Java HashSet 问题

    昨天,在百度的 java吧 看到有人问关于 HashSet 的问题.下面是他贴出的代码: import java.util.HashSet; public class JavaTest { publi ...

  8. Caused by: java.lang.IllegalArgumentException: @EnableAsync annotation metadata was not injected

    需要注意的是ComponentScan 不能扫描 org.springframework 否则会报错,要扫描指定的package才行

  9. resin配置

    第一种方式:      在本机调试Resin服务,一般是在Eclipse IDE中进行,这样即可以快速的在开发环境中启动/终止Resin,又可以很方便的Debug程序.跟踪异常栈.    在任何版本的 ...

  10. 滚动插件 animatescroll(可以设置要滚动到位置)

     1. 引入   <script src="js/animatescroll.js"></script> 2.设置要滚动到的位置  $('目标位置').an ...