Module.exports 和 exports
Module.exports 和 exports
在node中,没有全局作用域,只有模块作用域,外部访问不到内部,内部也访问不到外部,那么模块间如何通信
- 当加载一个模块的时候,被加载模块的代码在第一次加载的时候会执行一遍
module.exports
被加载模块可以使用 node 提供 的 module.exports 来绝对向外暴露的内容(不设置的话默认为一个空对象) module 在node.js 模块中一般都表示本模块的意思
require 函数真是实现:
function require(/* ... */) {
const module = { exports: {} }; // exports 默认为空对象
((module, exports) => {
// 模块代码在这。在这个例子中,定义了一个函数。
function someFunc() {}
exports = someFunc;
// 此时,exports 不再是一个 module.exports 的快捷方式,
// 且这个模块依然导出一个空的默认对象。
module.exports = someFunc;
// 此时,该模块导出 someFunc,而不是默认对象。
})(module, module.exports);
return module.exports;
}
exprot
export
和module.exports
指向的是同一个对象地址最终
require()
函数返回的是module.exports
中的数据以当
module.exports
属性被一个新的对象完全替代时 ,require
的数据肯定也会变成新值;但是,如果给export
对象改变地址的话,module.exports
不会改变,requrie
的值自然也就不会发生变化;可以将export
想象成module.exports
的快捷方式
module.exports与exports的区别
每一个node.js执行文件,都会创建一个module对象,同时,module对象会创建一个叫 exports 的属性,初始化的值是 { }
module.exports = { }
在模块的结尾,会将 module.exports 返回
return module.exports
说白了,exprots 是 引用的 module.exprots的值,moudule.exprots 被改变的时候 , exprots 不会被改变。 而模块导出的时候,真正导出的是 module.exprots, 而不是 exprots
实例解析
同目录下创建两个文件, a.js
, 和 b.js
在a.js
写入代码, 输出foo来看看b.js导出的模块到底是什么
var foo = require('./b')
console.log(foo)
b.js 什么也不写的情况下,
{ }
执行a.js 输出 一个空对象, 这也说明了我们的模块默认导出一个空对象
b.js 代码如下
exports.a = 1 //此时 执行 a.js 输出 :
// { a: 1 }
b.js 代码如下
module.exports.a = 2 exports.a = 1 //此时 执行 a.js 输出 :
// { a: 1 }
两句语句的操作其实是操作同一块对象地址,所以以最后的为准 a.js执行输出为1
b.js 代码如下
module.exports = {
a : 2
} exports.a = 1 //此时 执行 a.js 输出 :
// { a: 2 }
此时执行结果变为 2 为什么?
因为第次赋值操作的时候,本质是改变了 moudule.exprots 的地址, 为 module.exports 开辟了一块新的地址来存储数据 ,而 exprots 还是 连接着 原来的共享地址。 而模块最后导出的是 module.exports 这样应该就能理解其中的原因了吧
来一个复杂的
exports.a = 'aaa'
// module.exports = {
// a: 'aaa'
// }
module.exports.b = 123
// module.exports = {
// a: 'aaa',
// b: 123
// } exports = {
b: 456
}
// 此时 exports 和 module.exprots 断开联系,不再是同一片地址 module.exports.a = 'hahaha'
// module.exports = {
// a: 'hahaha',
// b: 123
// } exports.c = 456
// 断开联系 赋值无法作用与 modul.exports exports = module.exports
// 又指向同一片地址 exports.b = 789
// module.exports = {
// a: 'hahaha',
// b: 789
// }
最后输出
{ a: 'hahaha', b: 789 }
require
require一般导入下列三种包
- 内置核心模块
- 第三方模块
- 用户自己的模块
不可能有任何一个第三方包和核心模块的名字是一样的
模块查找机制
- 优先缓存
- 核心模块
- 路径形式的文件模块
- 第三方模块
当 Node 执行 require(A) 时,按下面处理
1. 当 A 是 内置模块
a, 返回该模块
b, 不在执行
2. 当 A 是 './' '/' '../' 开头的路径请求
a, 确定 A 所在的父模块, 确定 A 的 绝对路径
b, 将 A 当成文件 依次查找
- A
- A.js
- A.json
- A.node
只要其中有一个存在,就返回该文件,不再继续执行
c, 将 A 当成目录文件夹, 查找 A 文件夹下的下列文件
- A/package.json
- A/index.js
- A/index.json
- A/index.node
3. 当 A 属于第三方模块的时候
假想当前脚本文件 /home/akong/projects/foo.js 执行了 require('bar')
/home/akong/projects/node_modules/bar
/home/akong/node_modules/bar
/home/node_modules/bar
/node_modules/bar
node 会按照上面的顺序依次向上级的node_modules搜索bar
搜索时,node会先 bar 当成文件名 依次尝试加载下面这些文件,只要有一个成功就返回
bar
bar.js
bar.json
bar.node
如果都不成功,就将bar当做文件夹,搜索下面的文件
bar/package.json(main字段)
bar/index.js
bar/index.json
bar/index.node
杂记
在node中,全局模块的使用不需要加载,而非全局模块则需要加载。
process 模块在使用的时候无需通过 require( )来加载该函数,可以直接使用,而 fs 模块不是全局模块,需要加载来使用
var fs = require('fs')
Node 即是单线程的,又是异步非阻塞I/O
data 参数的数据类型是一个 buffer 对象 ,里面保存的就是一个一个的字节(理解为字符数组)
把buffer对象转化为字符串,用toString
方法 默认utf8
文件操作的
./
相对路径,相对的是执行 node 命令的路径解决:
__durbane
:表示当前正在执行的 js 文件所在的目录__filename
: 表示当前正在执行的 js 文件的完整路径两者都是本地变量,使用时不用加载
使用路径拼接的时候我们可以使用node提供的一个path模块,他可以更智能的识别反斜杠的存在和操作系统的兼容性,是我们的程序更简洁,兼容性更好
node 错误优先规则,在node回调中,一般都是用err当做第一个回调参数
try-catch 只能捕获 同步中的错误,异步中的错误无法用 trycatch来捕获,对于异步操作,要通过判断错误号(err.code)来进行出错处理
在请求服务器的时候,请求的url就只是一个标识,无其他作用
require 模块加载是同步的
当加载一个模块的时候,被加载模块的代码在第一次加载的时候会执行一遍,并缓存起来,后续加载的话就不会执行代码
node.js 遵循了 CommonJS 语法规范
在node中,没有全局作用域,只有模块作用域,外部访问不到内部,内部也访问不到外部
Module.exports 和 exports的更多相关文章
- nodejs里的module.exports和exports的关系
关于node里面的module.exports和exports的异同,网上已经有很多的资料,很多的文章,很多的博客,看了很多,好像懂了,又好像不懂,过几天又不懂了...大致总结是这样的: //下面这种 ...
- Node.js module.exports和exports的区别
require 用来加载代码,而 exports 和 module.exports 则用来导出代码,从接触node.js就不会它们两陌生,上代码: foo.js exports.a = functio ...
- node基础再现--module.exports 和exports
实际上,最最基础的方法,最最原始的方法是module.exports,至于exports,是为了方便书写才出来的,应该说,module.exports 包含exports,所工作的范围更加的广泛! m ...
- module.exports与exports,export和export default
还在为module.exports.exports.export和export default,import和require区别与联系发愁吗,这一篇基本就够了! 一.首先搞清楚一个基本问题: modu ...
- nodejs里的module.exports和exports
引 在node.js中我们可以使用module.exports和exports导出模块,设置导出函数.数组.变量等等 为什么可以用这两个模块? 或者直接问,node.js的模块功能是怎么实现的. 这样 ...
- module.exports与exports区别
CommonJS模块规范 Node应用由模块组成,采用CommonJS模块规范. 根据这个规范,每个文件就是一个模块,有自己的作用域.在一个文件里面定义的变量.函数.类,都是私有的,对其他文件不可见. ...
- module.exports与exports
API文档是枯燥的,下面本人收集了一些论坛经常有人疑问和开源代码中经常遇到的案例供大家研究一下. module.exports与exports的区别 每一个node.js执行文件,都自动创建一个mod ...
- node (02 CommonJs 和 Nodejs 中自定义模块)顺便讲讲module.exports和exports的区别 dependencies 与 devDependencies 之间的区别
CommonJS 规范的提出,主要是为了弥补当前 JavaScript 没有标准的缺陷.它的终极目标就是:提供一个类似 Python,Ruby 和 Java 语言的标准库,而不只是停留在小脚本程序的阶 ...
- (转)Node.js module.exports与exports
本文转自Node.js module.exports与exports 作者: chemdemo 折腾Node.js有些日子了,下面将陆陆续续记录下使用Node.js的一些细节. 熟悉Node.js的童 ...
- module.exports 与 exports
module.exports 与 exports 注意:1 对于要导出的属性,可以简单直接挂到 exports 对象上2 对于类,为了直接使导出的内容作为类的构造器可以让调用者使用 new 操作符创建 ...
随机推荐
- Spring 学习二-----AOP的原理与简单实践
一.Spring AOP的原理 AOP全名Aspect-Oriented Programming,中文直译为面向切面(方面)编程.何为切面,就比如说我们系统中的权限管理,日志,事务等我们都可以将其看 ...
- Ubuntu下ss的安装与使用
不得不说,linux真的有种让人用上就爱上的魔力,正好最近Ubuntu出了16.04,便索性装了个win10+Ubuntu的双系统,也算是告慰那永远留在老硬盘里的虚拟机吧. 言归正传,换上Ubuntu ...
- 楼控-西门子insight BBMD设置
BBMD设置的目的就是让两个不同网段的设备可以同时在一个系统中访问的操作. 比如你有两个bacnet的网络,但是一个是192.168.0.1-192.168.0.255的网段,另一个是10.0.0.1 ...
- 为什么用clojure作为storm 的主要开发语言
Why you choose Clojure as the development language of Storm? Could you talk about your long practica ...
- BZOJ 1455 罗马游戏 左偏树
题目大意:给定n个点,每一个点有一个权值,提供两种操作: 1.将两个点所在集合合并 2.将一个点所在集合的最小的点删除并输出权值 非常裸的可并堆 n<=100W 启示式合并不用想了 左偏树就是快 ...
- Mina airQQ聊天开门见山篇(一)
Mina airQQ聊天开门见山篇(一) 近期项目可能要用到Mina,这个礼拜就在看这个框架,所以想写个小小的聊天的demo来巩固下,打算用几篇博客来记录下相关的知识 client用的是Flex Ai ...
- luogu1955 [NOI2015] 程序自动分析
题目大意 假设x1,x2,x3...代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足.i, ...
- Windows 10 MBR转GPT分区
注意:分区有风险,操作需谨慎,提前备份好数据. 说明: 1.有“系统保留”的分区,可以直接删除,用来做GPT分区的UEFI启动分区. 2.没有“系统保留”分区的,需要在分区最前面调整分区大小,留出30 ...
- ES Segment Memory——本质上就是segment中加到内存的FST数据,因此segment越多,该内存越大
ElasticSearch优化系列四:ES的heap是如何被瓜分掉的 转自:https://www.jianshu.com/p/f41b706db6c7 以下分别解读几个我知道的内存消耗大户: Seg ...
- javaBean为什么要implements Serializable
转自:https://www.cnblogs.com/jqlbj/p/6261592.html 一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的.因此如果要序 ...