博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
nodejs模块中exports和module.exports的区别
阅读量:6090 次
发布时间:2019-06-20

本文共 3743 字,大约阅读时间需要 12 分钟。

通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 ,这些核心模块被编译成二进制文件,可以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();

clipboard.png

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);

结果:

clipboard.png

通过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);

结果:

clipboard.png

直接传给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的被覆盖了

clipboard.png

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

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

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

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

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

转载地址:http://tvmwa.baihongyu.com/

你可能感兴趣的文章
ALSA声卡驱动中的DAPM详解之六:精髓所在,牵一发而动全身
查看>>
libev与libuv的区别
查看>>
iOS 为什么使用xcode8上传app包到appStore无法构建版本
查看>>
Tomcat优化步骤【转】
查看>>
CRC 自动判断大端 小端
查看>>
原来这样可以轻松恢复回收站删除文件
查看>>
DisparityCostVolumeEstimator.cpp
查看>>
(转)git中关于fetch的使用
查看>>
mongo DB for C#
查看>>
caffe整体框架的学习的博客,这个博客山寨了一个caffe框架
查看>>
git只拉取github部分代码的方法
查看>>
[LeetCode] Construct Quad Tree 建立四叉树
查看>>
如何避免SHRINKDATABASE & SHRINKFILE 产生索引碎片(转载)
查看>>
【SSH网上商城项目实战02】基本增删查改、Service和Action的抽取以及使用注解替换xml...
查看>>
高阶函数简述 js
查看>>
Java CompletableFuture:allOf等待所有异步线程任务结束
查看>>
Highmaps网页图表教程之图表配置项结构与商业授权
查看>>
mysql 5.6.33发布
查看>>
java 获取URL链接 内容
查看>>
Linux 命令详解(二)awk 命令
查看>>