node.js module初步理解-(转载)
在开发一个复杂的应用程序的时候,我们需要把各个功能拆分、封装到不同的文件,在需要的时候引用该文件。没人会写一个几万行代码的文件,这样在可读性、复用性和维护性上都很差,几乎所有的编程语言都有自己的模块组织方式,比如Java中的包、C#中的程序集等,node.js使用模块和包来组织,其机制实现参照了CommonJS标准,虽未完全遵守,但差距不大,使用起来非常简单。
什么是模块
在node.js中模块与文件是一一对应的,也就是说一个node.js文件就是一个模块,文件内容可能是我们封装好的一些JavaScript方法、JSON数据、编译过的C/C++拓展等,在关于node.js的误会提到过node.js的架构

其中http、fs、net等都是node.js提供的核心模块,使用C/C++实现,外部用JavaScript封装。
创建、加载模块
模块在node.js中的概念很简单,看看如何创建一个我们自己的模块供开发复用。
在node.js中创建模块非常简单,一个文件就是一个模块,所以我们创建一个test.js文件就创建了一个模块
test.js

var name='';
function setName(n){
name=n;
}
function printName(){
console.log(name);
}

问题是怎么使外部访问这个module,我们知道客户端的JavaScript使用script标签引入JavaScript文件就可以访问其内容了,但这样带了的弊端很多,最大的就是作用域相同,产生冲突问题,以至于前端大师们想出了立即执行函数等方式,利用闭包解决。node.js使用exports和require对象来解决对外提供接口和引用模块的问题。
我们可以把模块中希望被外界访问的内容定义到exports对象中,对test.js稍作修改就可以了
test.js

var name='';
function setName(n){
name=n;
}
function printName(){
console.log(name);
}
exports.setName=setName;
exports.printName=printName;

这样我们在相同路径下创建index.js,使用require引用一下test.js module
index.js
var test=require('./test');
test.setName('Byron');
test.printName();

exports一个对象
有时候我们希望模块对外提供的使一个对象,修改一下test.js
test.js

var Student=function(){
var name='';
this.setName=function(n){
name=n;
};
this.printName=function(){
console.log(name) ;
};
};
exports.Student=Student;

这样我们对外提供了一个Student类,在使用的时候需要这样
var Student=require('./test').Student;
var student=new Student();
student.setName('Byron');
student.printName();
require('./test').Student 很丑陋的样子,我们可以简单修改一下exports方式,使require优雅一些
test.js

var Student=function(){
var name='';
this.setName=function(n){
name=n;
};
this.printName=function(){
console.log(name) ;
};
};
module.exports=Student;

这样我们的require语句就可以优雅一些了
var Student=require('./test');
很神奇的样子,不是说好的exports是模块公开的接口嘛,那么module.exports是什么东西?
module.exports与exports
事实的情况是酱紫的,其实module.exports才是模块公开的接口,每个模块都会自动创建一个module对象,对象有一个modules的属性,初始值是个空对象{},module的公开接口就是这个属性——module.exports。既然如此那和exports对象有毛线关系啊!为什么我们也可以通过exports对象来公开接口呢?
为了方便,模块中会有一个exports对象,和module.exports指向同一个变量,所以我们修改exports对象的时候也会修改module.exports对象,这样我们就明白网上盛传的module.exports对象不为空的时候exports对象就自动忽略是怎么回事儿了,因为module.exports通过赋值方式已经和exports对象指向的变量不同了,exports对象怎么改和module.exports对象没关系了。
大概就是这么过程

module.exports=exports={};
......
module.exports=new Object();
exports=xxx;//和new Object没有关系了,最后返回module.exports,所以改动都无效了

一次加载
无论调用多少次require,对于同一模块node.js只会加载一次,引用多次获取的仍是相同的实例,看个例子
test.js

var name='';
function setName(n){
name=n;
}
function printName(){
console.log(name);
}
exports.setName=setName;
exports.printName=printName;

index.js
var test1=require('./test'),
test2=require('./test');
test1.setName('Byron');
test2.printName();

执行结果并不是'',而是输出了test1设置的名字,虽然引用两次,但是获取的是一个实例
require搜索module方式
node.js中模块有两种类型:核心模块和文件模块,核心模块直接使用名称获取,比如最长用的http模块
var http=require('http');
在上面例子中我们使用了相对路径 './test'来获取自定义文件模块,那么node.js有几种搜索加载模块方式呢?
- 核心模块优先级最高,直接使用名字加载,在有命名冲突的时候首先加载核心模块
- 绝对路径
- 相对路径
- 查找node_modules目录,我们知道在调用 npm install <name> 命令的时候会在当前目录下创建node_module目录(如果不存在) 安装模块,当 require 遇到一个既不是核心模块,又不是以路径形式表示的模块名称时,会试图 在当前目录下的 node_modules 目录中来查找是不是有这样一个模块。如果没有找到,则会 在当前目录的上一层中的 node_modules 目录中继续查找,反复执行这一过程,直到遇到根 目录为止。
文件模块只能按照路径加载(可以省略默认的.js拓展名,不是的话需要显示声明书写)
node.js module初步理解-(转载)的更多相关文章
- node.js module初步理解
在开发一个复杂的应用程序的时候,我们需要把各个功能拆分.封装到不同的文件,在需要的时候引用该文件.没人会写一个几万行代码的文件,这样在可读性.复用性和维护性上都很差,几乎所有的编程语言都有自己的模块组 ...
- Node.js 的初步理解
Node.js 是一个采用C++语言编写的后端的 Javascript 的运行环境, 它使用了 google 的 V8虚拟机来解释和执行代码.Node.js 的有许多有用的内置的模块,比如 http, ...
- 如何發佈一個完整Node.js Module
本文會透過以下幾個段落,讓各位一步一步學習如何寫一個自已的Node.js Module並且發佈到npm package上 Node.js Module 結構 我們先建立一個 NodeModuleDem ...
- (转)Node.js module.exports与exports
本文转自Node.js module.exports与exports 作者: chemdemo 折腾Node.js有些日子了,下面将陆陆续续记录下使用Node.js的一些细节. 熟悉Node.js的童 ...
- 创建并发布node.js module
创建node.js module. 创建一个文件夹,用来存放module. Cd到新创建的文件夹,运行npm init,会提示输入package的信息. 可以按照这个视频的来输入.Test com ...
- Node.js & module system
Node.js & module system Node.js v10.9.0 Documentation https://nodejs.org/api/modules.html#module ...
- node.js module.exports & exports & module.export all in one
node.js module.exports & exports & module.export all in one cjs const log = console.log; log ...
- Node.js & module.exports & exports
Node.js & module.exports & exports https://www.cnblogs.com/xgqfrms/p/9493550.html exports &a ...
- Node.js module.exports和exports的区别
require 用来加载代码,而 exports 和 module.exports 则用来导出代码,从接触node.js就不会它们两陌生,上代码: foo.js exports.a = functio ...
随机推荐
- Sentinel全局Feign默认熔断设计实现
写在前面 用XMind画了一张导图记录Spring Cloud Alibaba的学习笔记(源文件对部分节点有详细备注和参考资料,由于太大就没展示全部,欢迎关注我的公众号:阿风的架构笔记 后台发送[导图 ...
- [C++]变量声明与定义的规则
声明与定义分离 Tips:变量能且仅能被定义一次,但是可以被多次声明. 为了支持分离式编译,C++将定义和声明区分开.其中声明规定了变量的类型和名字,定义除此功能外还会申请存储空间并可能为变量赋一个初 ...
- Ubuntu所有版本下载及更新源
官网:https://www.ubuntu.com/download/desktop没找到历史版本,且下载速度很慢在网易镜像站下载ubuntu:网址:http://mirrors.163.com/ub ...
- Vue和Node.js交互之token
博主最近工作的时候,公司后台使用的JAVA,在做登陆时总会传来一个token然后我存在了本地存储中或Vuex中,之后每一次请求把它带在请求头上,然后就好奇想要自己做一个后台服务器然后做一个完整的登陆的 ...
- 2021S软件工程——案例分析作业
2021S软件工程--案例分析作业 18231169 黄思为 项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任建) 这个作业的要求在哪里 案例分析作业 我在这个课程的目标是 了解并熟悉 ...
- 2021软工-CSDN APP分析
项目 内容 这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 案例分析作业要求 我在这个课程的目标是 提升软件开发能力,提高团队协作能力 这个作业在哪个具体方面 ...
- 支持rotate和大小限制的golang log库
支持大小限制和rotate的log库,还是很有必要的,前者让你不再操心磁盘被吃光,后者让查日志更方便. 但是在golang中没有太好的实现,看过一些开源的和自行实现的,都有几个不满意的地方,比如: 没 ...
- linux ptrace学习
ptrace提供了一种使父进程得以监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪.学习linux的ptrace是为学习android adbi框 ...
- POJ1456贪心(set或者并查集区间合并)
题意: 给你n商品,每个商品有自己的价值还有保质期,一天最多只能卖出去一个商品,问最大收益是多少? 思路: 比较好想的贪心,思路是这样,每一次我们肯定拿价值最大的,至于在那天拿 ...
- (翻译)Attacking Interoperability(攻击互操作性)in Black Hat 2009 研究报告
前言 攻击互操作性(Attacking Interoperability)是 Mark & Ryan & David 发表于 2009 年的美国黑帽大会(Black Hat)上的一份研 ...