From b291152801cd71cd286f9da7feab7753dd6db5e3 Mon Sep 17 00:00:00 2001 From: qianguyihao Date: Tue, 14 Apr 2020 15:06:43 +0800 Subject: [PATCH] =?UTF-8?q?update:=20CommonJS=20=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 10-ES6/07-ES6:Promise入门详解.md | 4 +- .../01-Node.js介绍和环境配置.md | 183 +++++++++++++++--- .../02-Node.js模块化规范:CommonJS.md | 179 +++++++++++++++-- .../03-Node.js内置模块:fs文件模块.md | 171 ++++++++++++++++ 16-前端进阶/01-前端常见专有名词.md | 6 + 5 files changed, 498 insertions(+), 45 deletions(-) create mode 100644 11-Node.js和模块化/03-Node.js内置模块:fs文件模块.md diff --git a/10-ES6/07-ES6:Promise入门详解.md b/10-ES6/07-ES6:Promise入门详解.md index 64dbc28..f465474 100644 --- a/10-ES6/07-ES6:Promise入门详解.md +++ b/10-ES6/07-ES6:Promise入门详解.md @@ -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); }); diff --git a/11-Node.js和模块化/01-Node.js介绍和环境配置.md b/11-Node.js和模块化/01-Node.js介绍和环境配置.md index bf558d6..af3f9b2 100644 --- a/11-Node.js和模块化/01-Node.js介绍和环境配置.md +++ b/11-Node.js和模块化/01-Node.js介绍和环境配置.md @@ -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 是全球最大的开源库生态系统。 ![](http://img.smyhvae.com/20180301_1540.png) 如上图所示: -- 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 版本所在目录下。我们建议 ![](http://img.smyhvae.com/20180302_1210.png) -### 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 推荐的国内加速镜像淘宝: -## 方式3:安装cnpm +## 方式4:安装cnpm - 项目地址: diff --git a/11-Node.js和模块化/02-Node.js模块化规范:CommonJS.md b/11-Node.js和模块化/02-Node.js模块化规范:CommonJS.md index 86f6135..c5473b1 100644 --- a/11-Node.js和模块化/02-Node.js模块化规范:CommonJS.md +++ b/11-Node.js和模块化/02-Node.js模块化规范:CommonJS.md @@ -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 在服务器端的实现举例 diff --git a/11-Node.js和模块化/03-Node.js内置模块:fs文件模块.md b/11-Node.js和模块化/03-Node.js内置模块:fs文件模块.md new file mode 100644 index 0000000..05655fa --- /dev/null +++ b/11-Node.js和模块化/03-Node.js内置模块:fs文件模块.md @@ -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文档: + +查阅文档时的常见规律: + +- 红色:表示已废弃。 + +- 绿色:表示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'); +``` + + + + + + diff --git a/16-前端进阶/01-前端常见专有名词.md b/16-前端进阶/01-前端常见专有名词.md index 187ff9b..7d40cd5 100644 --- a/16-前端进阶/01-前端常见专有名词.md +++ b/16-前端进阶/01-前端常见专有名词.md @@ -1,6 +1,12 @@ +## JS相关 + +- JS装饰器 + + + ## 性能相关 - 防抖和节流