持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情
前言
大家好呀,我是L同学。在上篇文章node知识点总结(五)中,我们学习了node相关知识点,包括全局模块、nodemon模块、本地安装和全局安装区别、更改镜像源、模块化等相关知识点。今天,在这篇文章中,我们来学习node的其他知识点,包括nodejs中的模块分类、模块作用域、导入导出模块、CommonJS规范等相关知识点。
模块分类
Node.js 中根据模块来源的不同,将模块分为了 3 大类,分别是:
- 内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http等)。
- 自定义模块(用户创建的每个
.js文件,都是自定义模块)。 - 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)。
无论是什么模块,我们都要使用 require() 去加载,然后才能使用。加载自定义的模块,需要加 ./ ,而且可以省略后缀 .js。
// 加载核心模块
const fs = require('fs');
// 加载第三方模块
const express = require('express');
// 加载自定义模块
const custom = require('./custom');
模块作用域
在Node.js中,用户创建的每个 .js 文件都是自定义模块。在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。模块作用域的好处是避免了全局变量污染。由于模块具有一个模块级别的作用域,则另一个JS文件就无法使用当前模块定义的内容。
导入导出模块
为了能正常使用加载的模块中的成员,CommonJS给出了标准,即
- 一个模块需要使用
module.exports导出需要共享的内容。 - 使用模块的JS文件需要使用
require()导入模块。 模块导出的是什么,另一个使用模块的JS文件得到的就是什么。
require()具有缓存效果。使用 require() 加载模块后,会缓存起来,下次再调用 require()加载相同模块的时候,直接使用缓存,而不是从新加载,从而大大提高了性能。
CommonJS规范
CommonJS规范的出现是为了实现模块化。模块化规范的种类有AMD、CMD、CommonJS(Node.js遵循CommonJS)、ES6。
Node.js遵循了CommonJS模块化规范,CommonJS规定了模块的特性和各模块之间如何相互依赖。
CommonJS 规定:
- 每个模块内部,module 变量代表当前模块。
- module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口。
- 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。
require()加载模块的机制
加载自定义模块和其他模块的机制有相同之处,也有不同之处,所以这里分开来看。
加载自定义模块
- 首次加载成功,会缓存模块。
- 下次从缓存中加载,速度更快。
- 加载自定义模块必须加
./,如果是其他路径,对应变化,否则会把它当做核心模块或者第三方模块。 - 加载自定义模块的时候,如果是
require('./abc')。 (1)优先加载相同名字的文件,加载一个叫做 abc 的文件。
(2)自动补 .js 后缀,然后加载 abc.js 文件。
(3)自动补 .json 后缀,然后加载 abc.json 文件。
(4)自动补 .node 后缀,然后加载 abc.node 文件。
(5)以上文件都没有,则报错 Cannot find module './abc'
加载核心模块和第三方模块
-
首次加载成功,会缓存模块。
-
下次从缓存中加载,速度更快。
-
加载模块一定
不能加./,否则会把它当做自定义模块。 -
加载模块的时候,如果是
require('haha')。 (1)优先加载核心模块。
(2)去查找并加载第三方模块,查找第三方模块的路径可以通过 module.paths 查看。
(3)加载第三方模块会从当前目录开始寻找node_modules文件夹,如果找到进入node_modules文件夹寻找对应的模块。如果没找到,进入上一级目录继续寻找node_modules,一直到根目录。如果一直没有找到,提示未找到模块。