初识node.js
模块化
认识模块化
什么是模块化
- 模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
编程领域中的模块化
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。
把代码进行模块化拆分的好处:
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
模块化规范
- 模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规侧。
例如:
使用什么样的语法格式来引用模块
在模块中使用什么样的语法格式向外暴露成员
模块化规范的好处:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用,利人利己。
node 中的模块化
node 中模块的分类
Node.js 中根据模块来源的不同,将模块分为了 3 大类,分别是:
内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)自定义模块(用户创建的每个 js 文件,都是自定义模块)第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
node 中的模块化规范
Node.js 遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。
CommonJS 规定:
- 每个模块内部,
module变量代表当前模块。 - module 变量是一个对象,它的
exports属性(即 module.exports)是对外的接口。 - 加载某个模块,其实是加载该模块的
module.exports属性 require()方法用于加载模块
加载模块
使用强大的require( )方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。
// 加载内置模块
const HTTP = require("http");
// 加载自定义模块
const TEST = require("./test");
// 加载三方模块 (三方模块使用前先要下载)
const MOMENT = require("moment");
注意:使用 require()方法加载其它模块时,会执行被加载模块中的代码。
模块作用域
什么是模块作用域
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
let userName = "张三";
let sayHi = function () {
console.log("Hi");
};
// 在另一个文件中
const TEST = require("./test");
console.log(TEST); // { }
// 在当前模块中,无法访问到test中的私有成员
模块作用域的好处
防止全部变量污染的问题
<!-- 模块a -->
<script>
var userName = "张三";
</script>
<!-- 模块b -->
<script>
var userName = "李四";
</script>
<script>
console.log(userName); // 李四
</script>
module 对象
在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息,打印如下:

module.exports 对象
在自定义模块中,可以使用
module.exports对象,将模块内的成员共享出去,供外界使用。外界用
require()方法导入自定义模块时,得到的就是 module.exports 所指向的对象。
exports 对象
- 由于
module.exports单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。 - 默认情况下,
exports和module.exports指向同一个对象。最终共享的结果,还是以 module.exports 指向的对象为准。
注意:
使用 require()方法导入模块时,导入的结果,永远以 module.exports 指向的对象为准。
为了防止混乱,建议大家不要在同一个模块中同时使用 exports 和 module.exports
http://dev.nodejs.cn/learn/expose-functionality-from-a-nodejs-file-using-exports
可以通过两种方式进行操作。
第一种方式是将对象赋值给 module.exports(这是模块系统提供的对象),这会使文件只导出该对象:
const car = { brand: "Ford", model: "Fiesta" };
module.exports = car;
//在另一个文件中
const car = require("./car");
第二种方式是将要导出的对象添加为 exports 的属性。这种方式可以导出多个对象、函数或数据:
const car = { brand: "Ford", model: "Fiesta" };
exports.car = car;
或直接
exports.car = {
brand: "Ford",
model: "Fiesta",
};
module.exports 和 export 之间有什么区别?
前者公开了它指向的对象。 后者公开了它指向的对象的属性。
模块的加载机制
优先从缓存中加载。
模块在第一次加载后会被缓存。这也意味着多次调用 require()不会导致模块的代码被执行多次。
注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。
内置模块的加载机制
- 内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高。
例如,require('fs')始终返回内置的 fs 模块,即使在 node _modules 目录下有名字相同的包也叫做 fs。
自定义模块的加载机制
使用 require( )加载自定义模块时,必须指定以./或../开头的路径标识符。在加载自定义模块时,如果没有指定./或../这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。
同时,在使用 require( )导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件
- 按照确切的文件名进行加载
- 补全
.js扩展名进行加载 - 补全
.json扩展名进行加载 - 补全
.node扩展名进行加载 - 加载失败,终端报错
第三方模块的加载机制
- 如果传递给 require()的模块标识符不是一个内置模块,也没有以'./'或'../'开头,则 Node.js 会从当前模块的父目录开始,尝试从/node_modules 文件夹中加载第三方模块。
- 如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。
node 中如何使用 ES6 的模块化?
http://www.ruanyifeng.com/blog/2020/08/how-nodejs-use-es6-module.html
ES6 模块和 CommonJS 模块有很大的差异。
语法上面,CommonJS 模块使用require()加载和module.exports输出,ES6 模块使用import和export。
用法上面,require()是同步加载,后面的代码必须等待这个命令执行完,才会执行。import命令则是异步加载,或者更准确地说,ES6 模块有一个独立的静态解析阶段,依赖关系的分析是在那个阶段完成的,最底层的模块第一个执行。
Node.js 要求 ES6 模块采用.mjs后缀文件名。也就是说,只要脚本文件里面使用import或者export命令,那么就必须采用.mjs后缀名。Node.js 遇到.mjs文件,就认为它是 ES6 模块,默认启用严格模式,不必在每个模块文件顶部指定"use strict"。
如果不希望将后缀名改成.mjs,可以在项目的package.json文件中,指定type字段为module。
如果这时还要使用 CommonJS 模块,那么需要将 CommonJS 脚本的后缀名都改成.cjs。如果没有type字段,或者type字段为commonjs,则.js脚本会被解释成 CommonJS 模块。
总结为一句话:.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置。
注意,ES6 模块与 CommonJS 模块尽量不要混用。require命令不能加载.mjs文件,会报错,只有import命令才可以加载.mjs文件。反过来,.mjs文件里面也不能使用require命令,必须使用import。
node 配置环境变量

将node_global文件夹的绝对路径添加到 path 环境变量中
终端命令
↑键 | 快速定位到上一次执行的命令 |
|---|---|
Tab键 | 能够快速补全路径 |
Esc键 | 清空当前已输入的命令 |
cls命令 | 清空终端 |
如何快速切换node版本
可以使用如下工具切换:
n
n:n 是 npm 中的一个包,用来切换 node 版本,需要使用 n,就必须要下载 node 环境
# 全局安装
npm install -g n
# 查看n的版本
n --version
# 查看可供下载的所有node版本,回车后将会显示所有的node版本,使用上下键,来选择node版本,然后回车即可
n
# 下载最新的node版本
n latest
# 删除指定的node版本
n rm <version>
# 使用对应的node版本
n <version>
nvm
nvm 是一个单独的软件,需要下载,不需要 node 环境,如已经安装 node,需要卸载,以及环境变量,和全局包。
只能 mac 使用
nvm-window
nvm-window 和 nvm 功能一样,但是并不是 nvm 的 window 版本,是由其他人开发的供 window 使用的 node 版本管理工具。
安装前须知
- 安装路径上不要有中文字符或者空格,否则会出现错误
- 如已经安装 node,需要卸载,以及环境变量,和全局包。
下载.exe结尾的文件来安装,一般安装完成会自动配置环境变量
# 列出 Node.js 的安装目录,默认是 NVM 的安装目录
nvm root
# 设置 Node.js 的安装目录;
nvm root <path>
# 列出已经安装的 Node.js 的版本号,正在使用的版本前标有星号
nvm list
# 列出所有可以安装的 Node.js 的版本
nvm list available
# 安装指定版本的 Node.js
nvm install <version>
# 安装最新的 LTS(稳定版) 版的 Node.js
nvm install lts
# 安装最新版的 Node.js
nvm install latest
# 卸载指定版本的 Node.js
nvm uninstall <version>:
# 使用指定版本的 Node.js
nvm use <version>
#使用最新的 LTS 版的 Node.js,要是没安装就无法用
nvm use lts
#使用最新版的 Node.js,要是没安装就无法用
nvm use latest
#使用最新安装的 Node.js;
nvm use newest 使用最新安装的 Node.js;
# 列出当前使用的 Node.js 的版本(也可以使用 nvm list)。
nvm current
#使用 nvm use 需要以管理员的身份打开 PowerShell。