模块化
什么是模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。 对于整个系统来说,模块是可组合、分解和更换的单元。
生活中的模块化
编程中的模块化
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。
把代码进行模块化拆分的好处:
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
- etc…
模块化规范
模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。
例如:
- 使用什么样的语法格式来引用模块 (require(‘fs’))
- 在模块中使用什么样的语法格式向外暴露成员 (目前没有学习,马上学习)
模块化规范的好处:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用, 利人利己。
我们自己写模块,也要遵守模块化的标准。
Node.js 中模块的分类
Node.js 中根据模块来源的不同,将模块分为了 3 大类,分别是:
- 内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)
- 自定义模块(用户创建的每个
.js
文件,都是自定义模块) - 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
加载模块
// 加载核心模块
const fs = require('fs');// 加载第三方模块
const express = require('express');// 加载自定义模块
const custom = require('./custom');
使用 require()
加载模块后,会缓存起来,下次再调用 require()
加载相同模块的时候,直接使用缓存,而不是从新加载,从而大大提高了性能。
注意事项:
- 无论是什么模块,我们都要使用
require()
去加载,然后才能使用。 - 加载自定义的模块,需要加
./
,而且可以省略后缀.js
自定义模块的实现(重点)
Node.js中的模块作用域
在 Node.js 中,用户创建的每个 .js
文件都是自定义模块。 在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
模块作用域的好处是避免了全局变量污染。
导出导入模块
为了能正常使用加载的模块中的成员,CommonJS给出了标准,即
- 一个模块需要使用
module.exports
导出需要共享的内容。 - 使用模块的JS文件需要使用
require()
导入模块。
模块导出的是什么,另一个使用模块的JS文件得到的就是什么。
了解CommonJS规范
为了实现模块化。
模块化规范的种类:
- AMD
- CMD
- CommonJS — Node.js 遵循CommonJS
- ES6
Node.js 遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。
CommonJS 规定:
- 每个模块内部,module 变量代表当前模块。
- module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口。
- 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。
require() 加载模块的机制
加载自定义模块和其他模块的机制有相同之处,也有不同之处,所以这里分开来看。
加载自定义模块
- 首次加载成功,会缓存模块
- 下次从缓存中加载,速度更快
- 加载模块必须加
./
,如果是其他路径,对应变化,否则会把它当做核心模块或者第三方模块 - 加载模块的时候,如果是
require('./abc')
- 优先加载相同名字的文件,加载一个叫做 abc 的文件
- 自动补
.js
后缀,然后加载abc.js
文件 - 自动补
.json
后缀,然后加载abc.json
文件 - 自动补
.node
后缀,然后加载abc.node
文件 - 以上文件都没有,则报错
Cannot find module './abc'
加载核心模块和第三方模块
- 首次加载成功,会缓存模块
- 下次从缓存中加载,速度更快
- 加载模块一定
不能
加./
,否则会把它当做自定义模块 - 加载模块的时候,如果是
require('haha')
- 优先加载核心模块
- 去查找并加载第三方模块,查找第三方模块的路径可以通过
module.paths
查看