一. 邂逅Node.js
1.1. 对Node的认识
1.1.1. Node的概念理解
- Node.js是一个基于V8 JavaScript引擎的JavaScript运行时环境
V8可以嵌入到任何C ++应用程序中,无论是Chrome还是Node.js,事实上都是嵌入了V8引擎来执行JavaScript代码; 但是在Chrome浏览器中,还需要解析、渲染HTML、CSS等相关渲染引擎,另外还需要提供支持浏览器操作的API、浏览器自己的事件循环等 在Node.js中我们也需要进行一些额外的操作,比如文件系统读/写、网络IO、加密、压缩解压文件等操作
1.1.2. Node和浏览器区别
在浏览器中,全局变量都是在window上的,比如有document、setInterval、setTimeout、alert、console等等
在浏览器中执行的JavaScript代码,如果我们在顶级范围内通过var定义的一个属性,默认会被添加到window对象上
在Node中,我们也有一个global属性,并且看起来它里面有很多其他对象
在node中,我们通过var定义一个变量,它只是在当前模块中有一个变量,不会放到全局中
1.2. Node的应用场景
- 前端开发的库
- npm、yarn、pnpm工具成为前端开发使用最多的工具
- 使用Node.js作为web服务器开发、中间件、代理服务器
- Node.js完成前后端渲染的同构应用
- 编写脚本工具
- 使用Electron来开发桌面应用程序
1.3. Node的安装
1.3.1. 安装Node的LTS版本
- LTS版本:(Long-term support, 长期支持)相对稳定一些,推荐线上环境使用该版本;
- Current版本:最新的Node版本,包含很多新特性;
1.4. Node的输入和输出
-
输出: console.log
-
输入: node aaa.js 参数
- process.argv
// 输出的内容
console.log("Hello World");
const num1 = 10;
const num2 = 20;
console.log(num1 + num2);
// 2.给程序输入内容
const arg1 = process.argv[2];
const arg2 = process.argv[3];
console.log(arg1, arg2);
1.5. Node的全局对象
1.5.1. 特殊的全局对象
- __dirname:获取当前文件所在的路径
- __filename: 获取当前文件所在的路径和文件名称
- exports/require/module.exports
// 1.类似于window的全局对象
console.log(global);
// 2.特殊的全局对象
// __dirname当前的文件所在的目录结构
console.log(__dirname);
// __filename当前目录文件名称
console.log(__filename);
1.5.2. 其他的全局对象
-
process
-
console
-
定时器
- setTimeout
- setInterval
- setImmediate
- process.next
-
global
-
和window的区别
在浏览器中执行的JavaScript代码,如果我们在顶级范围内通过var定义的一个属性,默认会被添加到window对象上
在node中,我们通过var定义一个变量,它只是在当前模块中有一个变量,不会放到全局中
-
globalThis
-
二. 前端模块化
2.1. 认识模块化
-
对模块化概念的理解
目的是将程序划分成一个个小的结构
这个结构中编写属于自己的逻辑代码,有自己的作用域,定义变量名词时不会影响到其他的结构
这个结构可以将自己希望暴露的变量、函数、对象等导出给其结构使用
也可以通过某种方式,导入另外结构中的变量、函数、对象等
-
早期是没有模块化, 带来一些问题
- 命名冲突 -> 立即执行函数 -> 自定义模块 -> 没有规范
- 社区中模块化规范: CommonJS/AMD/CMD
- ES6中推出模块化: ES Module
2.2. CommonJS
2.2.1. Node基础使用
- exports导出
util.js
const UTI_NAME = "util_name";
function formatCount() {
return "500万"
}
function formatDate() {
return "2023-03-02"
}
exports.UTI_NAME = UTI_NAME;
exports.formatCount = formatCount;
exports.formatDate = formatDate;
- require导入
main.js
// 1.直接获取导出的对象,从对象中获取属性
// const util = require("./util.js");
// console.log(util.UTI_NAME);
// console.log(util.formatCount());
// console.log(util.formatDate());
// 2.导入对象之后,直接对其进行解构
const { UTI_NAME, formatCount, formatDate } = require("./util.js");
console.log(UTI_NAME);
console.log(formatCount);
console.log(formatDate);
2.2.2. exports的本质
- exports和require指向是同一个对象: 引入赋值
2.2.3. module.exports
-
module.exports和exports的关系:
- 默认指向的是同一个对象
-
require本质查找的module.exports的对象
-
module.exports赋值新的对象
- exports就没有什么意义
foo.js
const name = "foo";
const age = 18;
function sayHello() {
console.log("sayHello");
}
// 1.在开发中使用的很少
// exports.name = name;
// exports.age = age;
// exports.sayHello = sayHello;
const name = "foo";
const age = 18;
function sayHello() {
console.log("sayHello");
}
// 1.在开发中使用的很少
// exports.name = name;
// exports.age = age;
// exports.sayHello = sayHello;
// 2.将模块中内容导出
// 结论: Node导出的本质是在导出module.exports对象
// module.exports.name = name;
// module.exports.age = age;
// module.exports.sayHello = sayHello;
// console.log(exports.name, "-------");
// console.log(exports.age, "-------");
// console.log(exports.sayHello, "-------");
// console.log(exports === module.exports);
// 3.开发中常见的写法
module.exports = {
name,
age,
sayHello
}
// exports.name = "哈哈哈";
// module.exports.name = "哈哈哈";
mian.js
const foo = require("./foo.js");
console.log(foo.name);
console.log(foo.age);
foo.sayHello();
2.2.4. require导入解析
- 情况一: 内置模块path、http
- 情况二: 路径
- 情况三: 从node_modules查找
require 查找规则
情况一:X是一个Node核心模块,比如path、http
- 直接返回核心模块,并且停止查找
情况二:直接是一个X(没有路径),并且X不是一个核心模块
- 从node_modules查找
情况三:X是一个Node核心模块,比如path、http
第一步:将X当做一个文件在对应的目录下查找;
.如果有后缀名,按照后缀名的格式查找对应的文件
如果没有后缀名,会按照如下顺序:
直接查找文件X
查找X.js文件
查找X.json文件
查找X.node文件
第二步:没有找到对应的文件,将X作为一个目录
查找目录下面的index文件
查找X/index.js文件
查找X/index.json文件
查找X/index.node文件
如果没有找到,那么报错:not found
2.2.5. 模块的加载过程
-
结论一: 在第一次导入模块时, 代码会被执行一次
-
结论二: 多次导入只会执行一次
- module对象.loaded
-
结论三: 循环引入(图结构)
- 深度优先算法
2.3. AMD/CMD规范
-
AMD主要是应用于浏览器的一种模块化规范
- 它采用的是异步加载模块
- AMD实现的比较常用的库是require.js和curl.js
-
CMD规范也是应用于浏览器的一种模块化规范
-
它也采用的也是异步加载模块,但是它将CommonJS的优点吸收了过来
-
CMD也有自己比较优秀的实现方案
- SeaJS
-