update: CommonJS 规范
This commit is contained in:
		
							parent
							
								
									d6b0277f05
								
							
						
					
					
						commit
						b291152801
					
				@ -237,12 +237,12 @@ Promise对象, 可以**将异步操作以同步的流程表达出来**。使用
 | 
			
		||||
                    return request2();
 | 
			
		||||
                })
 | 
			
		||||
                .then(data => {
 | 
			
		||||
                    // 接口2请求成功后,打印接口1的返回结果
 | 
			
		||||
                    // 接口2请求成功后,打印接口2的返回结果
 | 
			
		||||
                    console.log(data);
 | 
			
		||||
                    return request3();
 | 
			
		||||
                })
 | 
			
		||||
                .then(data => {
 | 
			
		||||
                    // 接口3请求成功后,打印接口1的返回结果
 | 
			
		||||
                    // 接口3请求成功后,打印接口3的返回结果
 | 
			
		||||
                    console.log(data);
 | 
			
		||||
                });
 | 
			
		||||
        </script>
 | 
			
		||||
 | 
			
		||||
@ -2,39 +2,43 @@
 | 
			
		||||
 | 
			
		||||
## Node.js的介绍
 | 
			
		||||
 | 
			
		||||
### 什么是 Node.js(官方解释)
 | 
			
		||||
### 什么是 Node.js
 | 
			
		||||
 | 
			
		||||
Node.js 是一个基于 **Chrome V8** 引擎的 JavaScript 代码运行环境。
 | 
			
		||||
Node.js 是一个基于 **Chrome V8** 引擎的 JavaScript 运行环境。Node.js使用了一个**事件驱动**、**非阻塞式I/O**的模型( Node.js的特性),使其轻量级又高效。Node.js 的包管理工具 npm 是全球最大的开源库生态系统。
 | 
			
		||||
 | 
			
		||||
Node.js使用了一个**事件驱动**、**非阻塞式I/O**的模型( Node.js的特性),使其轻量级又高效。
 | 
			
		||||
 | 
			
		||||
Node.js 的包管理器 npm 是全球最大的开源库生态系统。
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
如上图所示:
 | 
			
		||||
 | 
			
		||||
- Node 内部采用 Google Chrome 的 V8 引擎,作为 JavaScript 语言解释器;
 | 
			
		||||
- Node.js 不是一门语言,也不是 JavaScript 的框架,**Node.js是 JavaScript 语言在服务器端的运行环境(平台)**。
 | 
			
		||||
 | 
			
		||||
- 通过自行开发的 libuv 库,调用操作系统资源。
 | 
			
		||||
- Node.js 内部采用 Google Chrome 的 V8 引擎,作为 JavaScript 语言解释器;同时结合自行开发的 libuv 库,扩展了 JS 的功能,使得 JS 既可以在前端进行DOM操作(浏览器端),又可以在后端调用操作系统资源(I/O操作、文件读写、数据库操作等),是目前最简单的全栈式语言。
 | 
			
		||||
 | 
			
		||||
### Node.js的特点
 | 
			
		||||
 | 
			
		||||
- 事件驱动
 | 
			
		||||
 | 
			
		||||
### 什么是 Node.js(非官方解释)
 | 
			
		||||
- 非阻塞IO模型(异步)
 | 
			
		||||
 | 
			
		||||
**Node.js是 JavaScript 语言在服务器端的运行环境(平台)**。Node.js 不是一门语言,也不是 JavaScript 的框架。
 | 
			
		||||
 | 
			
		||||
- 与PHP、JSP、Python、Perl、Ruby的“既是语言,也是平台”不同,Node.js的使用JavaScript进行编程,运行在 Chrome 的 V8 引擎上。
 | 
			
		||||
 | 
			
		||||
- 与PHP、JSP等相比(PHP、JSP、.net都需要运行在服务器程序上,Apache、Naginx、Tomcat、IIS。
 | 
			
		||||
),Node.js跳过了Apache、Naginx、IIS等HTTP服务器,它自己不用建设在任何服务器软件之上。Node.js的许多设计理念与经典架构(LAMP = Linux + Apache + MySQL + PHP)有着很大的不同,可以提供强大的伸缩能力。Node.js没有web容器。
 | 
			
		||||
- 轻量和高效
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 运行环境(平台)的含义
 | 
			
		||||
 | 
			
		||||
- 首先,JavaScript 语言通过 Node 在服务器上运行,在这个意义上,Node 有点像 JavaScript 虚拟机。
 | 
			
		||||
首先,JavaScript 语言通过 Node 在服务器上运行,在这个意义上,Node 有点像 JavaScript 虚拟机。
 | 
			
		||||
 | 
			
		||||
其次,Node 生态系统活跃,提供了大量的开源库,使得 JavaScript 语言能与操作系统进行交互(比如读写文件、新建子进程),在这个层次上,Node 又是属于 JavaScript 的工具库。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**引申**:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
与PHP、JSP、Python、Perl、Ruby的“既是语言,也是平台”不同,Node.js的使用JavaScript进行编程,运行在 Chrome 的 V8 引擎上。
 | 
			
		||||
 | 
			
		||||
与PHP、JSP等相比(PHP、JSP、.net都需要运行在服务器程序上,Apache、Naginx、Tomcat、IIS。
 | 
			
		||||
),Node.js跳过了Apache、Naginx、IIS等HTTP服务器,它自己不用建设在任何服务器软件之上。Node.js的许多设计理念与经典架构(LAMP = Linux + Apache + MySQL + PHP)有着很大的不同,可以提供强大的伸缩能力。Node.js没有web容器。
 | 
			
		||||
 | 
			
		||||
- 其次,Node 生态系统活跃,提供了大量的开源库,使得 JavaScript 语言能与操作系统进行交互(比如读写文件、新建子进程),在这个层次上,Node 又是属于 JavaScript 的工具库。
 | 
			
		||||
 | 
			
		||||
## Node.js和服务器端开发
 | 
			
		||||
 | 
			
		||||
@ -68,15 +72,15 @@ Node.js 的包管理器 npm 是全球最大的开源库生态系统。
 | 
			
		||||
 | 
			
		||||
**1、中间层**。
 | 
			
		||||
 | 
			
		||||
前端访问中间层,中间层再访问后台的 Java/C++ 服务。这样做的好处是:安全性(不会把主服务器暴露在外面)、提高性能(做缓存等)、降低主服务器的复杂度。
 | 
			
		||||
前端访问中间层的接口,中间层再访问后台的 Java/C++ 服务。这样做的好处是:安全性(不会把主服务器暴露在外面)、提高性能(做缓存等)、降低主服务器的复杂度。
 | 
			
		||||
 | 
			
		||||
当然,有时候做 Node.js 开发,是因为:后台人力不够,所以把后台开发的一部分工作量,转移给前端同学。
 | 
			
		||||
 | 
			
		||||
**2、公司内部工具**。
 | 
			
		||||
**2、做公司内部工具、项目构建工具**。
 | 
			
		||||
 | 
			
		||||
**3、小型服务**(比如管理系统)。
 | 
			
		||||
**3、做小型服务、小型网站的后端**(比如管理系统)。
 | 
			
		||||
 | 
			
		||||
需要声明的是:Node.js很难像 Java/C++ 那样,成为后台的主力开发语言。这并非是因为 Node.js的性能问题(实际上,Node.js的性能还不错),主要是因为,Node.js的框架的支持度不够,很难独立成为后台开发语言。
 | 
			
		||||
需要声明的是:目前来看,Node.js很难像 Java/C++ 那样,成为后台的主力开发语言。这并非是因为 Node.js的性能问题(实际上,Node.js的性能还不错),主要是因为,Node.js的框架的支持度不够,很难独立成为后台开发语言。
 | 
			
		||||
 | 
			
		||||
### Node.js 的组成
 | 
			
		||||
 | 
			
		||||
@ -104,6 +108,8 @@ ECMAScript 是 JS 的语法;DOM 和 BOM 浏览器运行环境为 JS 提供的A
 | 
			
		||||
 | 
			
		||||
### Node 的历史
 | 
			
		||||
 | 
			
		||||
Node.js 诞生于 2009 年,由 Joyent 的员工 Ryan Dahl 开发而成, 目前官网最新版本已经更新到 13.x.x版本,最新稳定的是10.15.3。
 | 
			
		||||
 | 
			
		||||
- 2008年左右,随着 Ajax 的逐渐普及,Web 开发逐渐走向复杂化,系统化;
 | 
			
		||||
 | 
			
		||||
- 2009年2月,Ryan Dahl 想要创建一个轻量级,适应现代 Web 开发的平台;
 | 
			
		||||
@ -525,7 +531,7 @@ NPM 默认安装到当前正在使用 Node 版本所在目录下。我们建议
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### NPM的常用命令
 | 
			
		||||
## NPM的常用命令
 | 
			
		||||
 | 
			
		||||
查看 npm 当前版本:
 | 
			
		||||
 | 
			
		||||
@ -545,7 +551,8 @@ npm install npm@latest -g
 | 
			
		||||
```bash
 | 
			
		||||
npm init
 | 
			
		||||
 | 
			
		||||
npm init --yes 默认配置
 | 
			
		||||
# 快速跳过问答式界面,选择默认配置
 | 
			
		||||
npm init --yes
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
只在当前工程下安装指定的包:
 | 
			
		||||
@ -554,12 +561,125 @@ npm init --yes 默认配置
 | 
			
		||||
npm install [package]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
在全局阿浑惊吓安装指定的包:
 | 
			
		||||
在全局安装指定的包:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
npm install -g [package]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
安装的包只用于开发环境,不用于生产环境:(会出现在 package.json 文件中的 devDependencies 属性中)
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm install [package] --save-dev
 | 
			
		||||
 | 
			
		||||
# 或者
 | 
			
		||||
npm install [package] -D
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
安装的包需要发布到生产环境:(会出现在 package.json 文件中的 dependencies 属性中)
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm install [package] --save
 | 
			
		||||
 | 
			
		||||
# 或者
 | 
			
		||||
npm install [package] -S
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
查看当前目录下已安装的node包:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm list
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
查看全局已经安装的node包:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm list -g
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
查看npm帮助命令:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm --help
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
查看指定命令的帮助:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm [指定命令] --help
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
更新指定的包:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm update [package]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
卸载指定的包:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm uninstall [package]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
查看配置信息:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm config list
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
查看本地安装的指定包的信息,没有则显示empty:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm ls [package]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
查看全局安装的指定包的信息,没有则显示empty:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm ls [package] -g
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
查看远程npm上指定包的所有版本信息:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm info [package]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
查看当前包的安装路径:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm root
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
查看全局包的安装路径:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm root -g
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 配置 npm 镜像源
 | 
			
		||||
 | 
			
		||||
由于 npm 默认的下载地址在国外(npmjs.com),有时候会被墙,导致无法下载或者下载很慢。因此,我们可以尝试切换成,从其他的镜像源下载npm包。
 | 
			
		||||
@ -568,9 +688,11 @@ npm install -g [package]
 | 
			
		||||
 | 
			
		||||
- 方式1:临时切换镜像源。
 | 
			
		||||
 | 
			
		||||
- 方式2:通过 NRM 切换镜像源(最为推荐的方式)。
 | 
			
		||||
- 方式2:切换镜像源
 | 
			
		||||
 | 
			
		||||
- 方式3:cnpm。
 | 
			
		||||
- 方式3:通过 NRM 切换镜像源(最为推荐的方式)。
 | 
			
		||||
 | 
			
		||||
- 方式4:cnpm。
 | 
			
		||||
 | 
			
		||||
下面来分别讲一下。
 | 
			
		||||
 | 
			
		||||
@ -586,8 +708,15 @@ npm install [package] --registry [https://xxx]
 | 
			
		||||
npm install express --registry https://registry.npm.taobao.org
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 方式2:切换镜像源
 | 
			
		||||
 | 
			
		||||
### 方式2:通过 NRM 切换镜像源(推荐)
 | 
			
		||||
```bash
 | 
			
		||||
npm config set registry https://registry.npm.taobao.org
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
执行上述命令后,以后下载所有 npm 包的时候,都会改为使用淘宝的镜像源。
 | 
			
		||||
 | 
			
		||||
### 方式3:通过 NRM 切换镜像源(推荐)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**NRM**:Node Registry Manager。作用是:**切换和管理npm包的镜像源**。
 | 
			
		||||
@ -624,7 +753,7 @@ nrm use taobao
 | 
			
		||||
推荐的国内加速镜像淘宝:<https://npm.taobao.org/>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 方式3:安装cnpm
 | 
			
		||||
## 方式4:安装cnpm
 | 
			
		||||
 | 
			
		||||
- 项目地址:<https://npm.taobao.org/>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -139,48 +139,195 @@ PS:面试时,经常会问AMD 和 CMD 的区别。
 | 
			
		||||
 | 
			
		||||
- 在浏览器端: 模块需要提前编译打包处理。首先,既然同步的,很容易引起阻塞;其次,浏览器不认识`require`语法,因此,需要提前编译打包。
 | 
			
		||||
 | 
			
		||||
### 模块的暴露和引入
 | 
			
		||||
 | 
			
		||||
### 暴露模块的方式
 | 
			
		||||
Node.js 中只有模块作用域,两个模块之间的变量、方法,默认是互不冲突,互不影响,这样就导致一个问题:模块 A 要怎样使用模块B中的变量&方法呢?这就需要通过 `exports` 关键字来实现。
 | 
			
		||||
 | 
			
		||||
**方式一**:
 | 
			
		||||
Node.js中,每个模块都有一个 exports 接口对象,我们可以把公共的变量、方法挂载到这个接口对象中,其他的模块才可以使用。
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
  module.exports = value
 | 
			
		||||
接下来详细讲一讲模块的暴露、模块的引入。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 暴露模块的方式一: exports
 | 
			
		||||
 | 
			
		||||
`exports`对象用来导出当前模块的公共方法或属性。别的模块通过 require 函数调用当前模块时,得到的就是当前模块的 exports 对象。
 | 
			
		||||
 | 
			
		||||
**语法格式**:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
// 相当于是:给 exports 对象添加属性
 | 
			
		||||
exports.xxx = value
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
这个 value 可以是任意的数据类型。
 | 
			
		||||
 | 
			
		||||
**方式二**:
 | 
			
		||||
**注意**:暴露的关键词是`exports`,不是`export`。其实,这里的 exports 类似于 ES6 中的 export 的用法,都是用来导出一个指定名字的对象。
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
  exports.xxx = value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**代码举例**:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const name = 'qianguyihao';
 | 
			
		||||
exports.name = name;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**问题**: 暴露的模块到底是谁?
 | 
			
		||||
 | 
			
		||||
### 暴露模块的方式二: module.exports
 | 
			
		||||
 | 
			
		||||
`module.exports`用来导出一个默认对象,没有指定对象名。
 | 
			
		||||
 | 
			
		||||
语法格式:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
// 方式一:导出整个 exports 对象
 | 
			
		||||
module.exports = value;
 | 
			
		||||
 | 
			
		||||
// 方式二:给 exports 对象添加属性
 | 
			
		||||
module.exports.xxx = value;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
这个 value 可以是任意的数据类型。
 | 
			
		||||
 | 
			
		||||
代码举例:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
// 方式1
 | 
			
		||||
module.exports = {
 | 
			
		||||
    name: '我是 module1',
 | 
			
		||||
    foo(){
 | 
			
		||||
        console.log(this.name);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 我们不能再继续写 module.exports = value2。因为重新赋值,会把 exports 对象 之前的赋值覆盖掉。
 | 
			
		||||
 | 
			
		||||
// 方式2
 | 
			
		||||
const age = 28;
 | 
			
		||||
module.exports.age = age;
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`module.exports` 还可以修改模块的原始导出对象。比如当前模块原本导出的是一个对象,我们可以通过 module.exports 修改为导出一个函数。如下:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
module.exports = function () {
 | 
			
		||||
    console.log('hello world')
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### exports 和 module.exports 的区别
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
最重要的区别:
 | 
			
		||||
 | 
			
		||||
- 使用exports时,只能单个设置属性 `exports.a = a;`
 | 
			
		||||
 | 
			
		||||
- 使用module.exports时,既单个设置属性 `module.exports.a`,也可以整个赋值 `module.exports = obj`。
 | 
			
		||||
 | 
			
		||||
其他要点:
 | 
			
		||||
 | 
			
		||||
- Node中每个模块的最后,都会执行 `return: module.exports`。
 | 
			
		||||
 | 
			
		||||
- Node中每个模块都会把 `module.exports`指向的对象赋值给一个变量 `exports`,也就是说 `exports = module.exports`。
 | 
			
		||||
 | 
			
		||||
- `module.exports = XXX`,表示当前模块导出一个单一成员,结果就是XXX。
 | 
			
		||||
 | 
			
		||||
- 如果需要导出多个成员,则必须使用 `exports.add = XXX; exports.foo = XXX`。或者使用 `module.exports.add = XXX; module.export.foo = XXX`。
 | 
			
		||||
 | 
			
		||||
### 问题: 暴露的模块到底是谁?
 | 
			
		||||
 | 
			
		||||
**答案**:暴露的本质是`exports`对象。【重要】
 | 
			
		||||
 | 
			
		||||
比如,方式二可以理解成是,**给 exports 对象添加属性**。
 | 
			
		||||
比如,方式一的 `exports.a = a` 可以理解成是,**给 exports 对象添加属性**。方式二的 `module.exports = a`可以理解成是给整个 exports 对象赋值。方式二的 `module.exports.c = c`可以理解成是给 exports 对象添加属性。
 | 
			
		||||
 | 
			
		||||
PS:暴露的关键词是`exports`,不是`export`。
 | 
			
		||||
Node.js 中每个模块都有一个 module 对象,module 对象中的有一个 exports 属性称之为**接口对象**。我们需要把模块之间公共的方法或属性挂载在这个接口对象中,方便其他的模块使用。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 引入模块的方式:require
 | 
			
		||||
 | 
			
		||||
require函数用来在一个模块中引入另外一个模块。传入模块名,返回模块导出对象。
 | 
			
		||||
 | 
			
		||||
### 引入模块的方式
 | 
			
		||||
**语法格式**:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
require(xxx)
 | 
			
		||||
```js
 | 
			
		||||
const module1 = require('模块名');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
解释:
 | 
			
		||||
 | 
			
		||||
- 内置模块:xxx 为模块名(包名)
 | 
			
		||||
- 内置模块:require的是**包名**。
 | 
			
		||||
 | 
			
		||||
- 下载的第三方模块:xxx为模块名(包名)。
 | 
			
		||||
- 下载的第三方模块:require的是**包名**。
 | 
			
		||||
 | 
			
		||||
- 自定义模块:xxx为模块文件路径。
 | 
			
		||||
- 自定义模块:require的是**文件路径**。文件路径既可以用绝对路径,也可以用相对路径。后缀名`.js`可以省略。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**代码举例**:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const module1 = require('./main.js');
 | 
			
		||||
 | 
			
		||||
const module2 = require('./main');
 | 
			
		||||
 | 
			
		||||
const module3 = require('Demo/src/main.js');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**require()函数的两个作用**:
 | 
			
		||||
 | 
			
		||||
- 执行导入的模块中的代码。
 | 
			
		||||
 | 
			
		||||
- 返回导入模块中的接口对象。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 主模块
 | 
			
		||||
 | 
			
		||||
主模块是整个程序执行的入口,可以调度其他模块。
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# 运行main.js启动程序。此时,main.js就是主模块
 | 
			
		||||
$ node main.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 模块的初始化
 | 
			
		||||
 | 
			
		||||
一个模块中的 JS 代码仅在模块**第一次被使用时**执行一次,并且在使用的过程中进行初始化,然后会被缓存起来,便于后续继续使用。
 | 
			
		||||
 | 
			
		||||
代码举例:
 | 
			
		||||
 | 
			
		||||
(1)calModule.js:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var a = 1;
 | 
			
		||||
 | 
			
		||||
function add () {
 | 
			
		||||
  return ++a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.add = add;
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
(2)main.js:(在 main.js 中引入 hello.js 模块)
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var addModule1 = require('./calModule')
 | 
			
		||||
var addModule2 = require('./calModule')
 | 
			
		||||
 | 
			
		||||
console.log(addModule1.add());
 | 
			
		||||
console.log(addModule2.add());
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
在命令行执行 `node main.js` 运行程序,打印结果:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
2
 | 
			
		||||
3
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
从打印结果中可以看出,`calModule.js`这个模块虽然被引用了两次,但只初始化了一次。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## CommonJS 在服务器端的实现举例
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										171
									
								
								11-Node.js和模块化/03-Node.js内置模块:fs文件模块.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								11-Node.js和模块化/03-Node.js内置模块:fs文件模块.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,171 @@
 | 
			
		||||
 | 
			
		||||
## CommonJS 规范
 | 
			
		||||
 | 
			
		||||
CommonJS 规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口对象。加载某个模块,其实是加载该模块的 module.exports 对象。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
var x = 5;
 | 
			
		||||
var addX = function (value) {
 | 
			
		||||
	return value + x;
 | 
			
		||||
};
 | 
			
		||||
module.exports.x = x;
 | 
			
		||||
module.exports.addX = addX;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Node.js 的API文档
 | 
			
		||||
 | 
			
		||||
Node.js 的API文档: <https://nodejs.org/docs/latest-v8.x/api/index.html>
 | 
			
		||||
 | 
			
		||||
查阅文档时的常见规律:
 | 
			
		||||
 | 
			
		||||
- 红色:表示已废弃。
 | 
			
		||||
 | 
			
		||||
- 绿色:表示100%安全使用。
 | 
			
		||||
 | 
			
		||||
- 黄颜色:表示当前版本可用,其他版本不确定。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Node.js 中模块的分类
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Node.js 应用由模块组成,采用 CommonJS 模块规范。Node.js中的模块分为三种:
 | 
			
		||||
 | 
			
		||||
- 内置模块
 | 
			
		||||
 | 
			
		||||
- 第三方模块
 | 
			
		||||
 | 
			
		||||
- 自定义模块
 | 
			
		||||
 | 
			
		||||
下面简单介绍一下。
 | 
			
		||||
 | 
			
		||||
### 1、内置模块
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const process = require('process');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
 | 
			
		||||
console.log(process.version);
 | 
			
		||||
console.log(path.resolve('../'));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
require方法用于加载模块。
 | 
			
		||||
 | 
			
		||||
### 2、require 加载第三方包的机制
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const express = require('express');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
require 加载第三方包的机制:
 | 
			
		||||
 | 
			
		||||
(1)第三方包安装好后,这个包一般会存放在当前项目的 node_modules 文件夹中。我们找到这个包的 package.json 文件,并且找到里面的main属性对应的入口模块,这个入口模块就是这个包的入口文件。
 | 
			
		||||
 | 
			
		||||
(2)如果第三方包中没有找到package.json文件,或者package.json文件中没有main属性,则默认加载第三方包中的index.js文件。
 | 
			
		||||
 | 
			
		||||
(3)如果在 node_modules 文件夹中没有找到这个包,或者以上所有情况都没有找到,则会向上一级父级目录下查找node_modules文件夹,查找规则如上一致。
 | 
			
		||||
 | 
			
		||||
(4)如果一直找到该模块的磁盘根路径都没有找到,则会报错:can not find module xxx。
 | 
			
		||||
 | 
			
		||||
**3、自定义模块(module)**:
 | 
			
		||||
 | 
			
		||||
每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
 | 
			
		||||
 | 
			
		||||
举例:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
var example = require('./example.js');
 | 
			
		||||
console.log(example.x); // 5
 | 
			
		||||
console.log(example.addX(1)); // 6
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
今天这篇文章,重点讲一下内置模块中的 **fs 文件处理模块**。
 | 
			
		||||
 | 
			
		||||
## 文件读取
 | 
			
		||||
 | 
			
		||||
fs 的英文全称是 File System。fs 模块提供了很多api方法,我们首先应该学习的方法是**文件读取**。
 | 
			
		||||
 | 
			
		||||
Node中文件读取的方式主要有以下几种。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 异步读取文件 fs.readFile()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
语法格式:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
fs.readFile(file[, options], callback(error, data))
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
代码举例:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
fs.readFile('c:\\demo\1.txt', 'utf8', (err, data) => {
 | 
			
		||||
  if (err) throw err;
 | 
			
		||||
  console.log(data);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 同步读取文件 fs.readFileSync()
 | 
			
		||||
 | 
			
		||||
语法格式:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
fs.readFileSync(file[, options])
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
代码举例:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
try {
 | 
			
		||||
  const data = fs.readFileSync('c:\\demo\1.txt', 'utf8');
 | 
			
		||||
  console.log(data);
 | 
			
		||||
} catch(e) {
 | 
			
		||||
  // 文件不存在,或者权限错误
 | 
			
		||||
  throw e;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Node.js 中的异步操作
 | 
			
		||||
 | 
			
		||||
fs模块对文件的几乎所有操作都有同步和异步两种形式。例如:readFile() 和 readFileSync()。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
区别:
 | 
			
		||||
 | 
			
		||||
- 同步调用会阻塞代码的执行,异步则不会。
 | 
			
		||||
 | 
			
		||||
- 异步调用会将 读取任务 下达到任务队列,直到任务执行完成才会回调。
 | 
			
		||||
 | 
			
		||||
- 异常处理方面,同步必须使用 try catch 方式,异步可以通过回调函数的第一个参数。【重要】
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
 | 
			
		||||
console.time('async');
 | 
			
		||||
fs.readFile(path.join('C:\\Users\\qianguyihao\\Downloads', 'H.mp4'), (error, data) => {
 | 
			
		||||
    if (error) throw error;
 | 
			
		||||
    // console.log(data);
 | 
			
		||||
});
 | 
			
		||||
console.timeEnd('async');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
console.time('sync');
 | 
			
		||||
try {
 | 
			
		||||
    var data = fs.readFileSync(path.join('C:\\Users\\qianguyihao\\Downloads', 'H.mp4'));
 | 
			
		||||
    // console.log(data);
 | 
			
		||||
} catch (error) {
 | 
			
		||||
    throw error;
 | 
			
		||||
}
 | 
			
		||||
console.timeEnd('sync');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,12 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## JS相关
 | 
			
		||||
 | 
			
		||||
- JS装饰器
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 性能相关
 | 
			
		||||
 | 
			
		||||
- 防抖和节流
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user