异步
同步和异步: JS是单线程语言,同步会阻塞后面代码的执行,因此引入了异步
微任务和宏任务:
- 微任务:Promise.then、async、await
- 宏任务:setTimeout、setInterval、Ajax
事件循环机制(eventloop):
- 所有同步任务都在主线程上依次执行,形成一个执行栈(调用栈),异步任务则放入一个任务队列
- 从上到下,先将遇到的所有同步任务依次压入执行栈中执行,遇到微任务加到微任务队列中,遇到宏任务加到红任务队列中
- 执行完同步任务,取出微任务队列中的微任务执行其同步代码,遇到微任务添添加到微任务队列末尾,遇到宏任务添加到宏任务队列末尾,继续执行,把微任务全部执行完
- 微任务执行完后,取出宏任务队列中的宏任务执行其同步代码,遇到微任务添加到微任务队列末尾,遇到宏任务添加到宏任务队列末尾
- 每次执行完一个宏任务都去检查微任务队列是否有新的微任务,如果有,执行所有微任务后再继续执行宏任务
- 如此循环,直到执行完所有宏任务
Promise
-
Promise 是进行异步编程的新解决方案(旧方案是用回调函数,会产生回调地狱) Promise 支持链式调用,可以对异步操作进行封装
-
Promise 的基本形式:
const p = new Promise((resolve, reject) => {
//封装异步操作
setTimeout(() => {
//根据条件给Promise对象设置不同状态
}, 1000)
}).then(value => {
//成功时执行的操作
},
reason => {
//失败时执行的操作
})
resolve 回调函数:任务成功时调用,同时修改Promise对象的状态为成功
reject 回调函数:任务失败时调用,同时修改Promise对象的状态为失败
Promise 的三种状态:待定(pending)、成功(fulfilled)和失败(rejected)
- Promise 的 API:
- Promise.prototype.then:
then方法在promise执行结束后被调用,返回一个Promise对象
链式调用:只要状态改变就会一直调用then方法,可以通过返回一个pending状态的Promise对象中断链式调用 - Promise.prototype.catch:
catch方法是then方法的语法糖, 可以只在最后指定的失败的回调
前面任何操作出了异常, 都会通过异常穿透传到最后失败的回调中处理 - Promise.all
参数为包含 n 个 promise 的数组 ,返回一个新的Promise对象
新Promise对象的结果:所有promise都成功才为成功,只要有一个失败就为失败 - Promise.race
参数为包含 n 个 promise 的数组 ,返回一个新的Promise对象
新Promise对象的结果:第一个完成(最先改变状态)的promise的状态和结果
async 和 await
async:
- 作用:把一个有返回值的函数封装为一个Promise对象
- Promise对象的结果由 async 函数的返回值决定:
如果返回值为非Promise类型,promise的状态为成功,结果为返回值
如果返回值为Promise类型,promise的状态和结果为返回值promise的状态和结果
如果抛出异常,promise的状态为失败,结果为抛出的异常
await 表达式:
- 作用:接收成功的Promise对象的结果
- await 右侧的表达式一般为Promise对象,但也可以为其他值 如果是成功的Promise对象,await 返回的是该Promise对象的结果值 如果是失败的Promise对象,会抛出异常,需要通过 try...catch 进行捕获 如果是其他值,则直接将该值作为 await 的返回值
- await 必须写在 async 函数中,但 async 函数可以没有 await
JS继承
- 原型继承:将子类的prototype设置为父类的实例,继承到父类原型中的属性和方法
- 借用构造函数:在子类构造函数内部使用call或apply来调用父类构造函数,继承到父类的实例属性和方法
- 组合继承:将原型链继承与构造函数继承组合在一起
- class继承:extends + super
- 寄生式继承
- 寄生式组合继承
ES6 新增语法
const 和 let 关键字:
- const 用于声明常量且声明时必须进行赋值,let 用于声明变量
- const 和 let 具有块级作用域,不存在变量提升
- 存在暂时性死区,即如果块级作用域的内部外部有同名变量,在块级作用域中不会再访问外部的变量
新增数据类型: Symbol 和 BigInt
- Symbol:代表独一无二的值,最大的用法是用来定义对象的唯一属性名。
- BigInt:可以表示任意大小的整数。
变量的解构赋值: 将数组或对象中的值提取出来,一 一对应地赋值给变量
扩展运算符(...):
- 可以将数组进行拆解
- 用法:合并数组,函数接收不定量参数
模板字符串(反引号``):
- 可以解析变量,通过
${变量名}使变量可以直接随字符串一起输出 - 可以识别回车换行
- 可以通过
${fun}调用函数
箭头函数
- 箭头函数没有自己的this指向,而是使用上下文的this,因此this指向不能被改变
- 箭头函数没有原型属性 prototype
- 基于以上两点,箭头函数不能作为构造函数,不能使用new关键字
- 箭头函数没有arguments,可以使用
Promise
async await
class 类
- 类的性质:
- class 的本质还是 function
- 类有一个默认的构造器方法constructor ,通过 new 命令生成对象实例时自动调用该方法
- 类的数据类型就是函数,类本身就指向构造函数 。
- 类的所有方法都定义 在类的 prototype 属性上
- 变量名前加#表示私有属性,方法名前加_表示私有方法
- 类内部的 this 指向类的实例 ,通过 this 定义的属性是定义在实例对象上的,否则都是定义在原型上
- 类的继承: extends + super
Set 和 Map 数据结构
- Set:
允许存储任何类型的值,类似于数组,但是成员的值都是唯一的,没有重复的值
add()增加值has()查询size属性取得元素数量delete()和clear()删除元素
- Map:
保存键值对, 任何类型的值都可以作为键或值,构造函数Map可以接受一个数组作为参数
set()方法添加键/值对- get() 和
has()进行查询 size属性获取映射中的键/值对的数量delete()和clear()删除值
- WeakMap:
- 弱映射:弱映射中的键只能是**
Object**或者继承自Object的类型 - 作用:实现真正私有变量的一种新方式。私有变量会存储在弱映射中,以对象实例为键,以私有成员的字典为值
- WeakSet:
WeakSet的成员只能是对象,而不能是其他类型的值WeakSet不可遍历
Proxy/Reflect
- 代理是目标对象的抽象,它可以用作目标对象的替身,但又完全独立于目标对象。
- 可以通过捕获器对基本操作进行拦截并修改。
- Reflect 对象的方法与 Proxy 对象的方法 一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就使 Proxy 对象可以方便地调用对应的 Reflect 方法来完成默认行为,作为修改行为
ES6模块化 Module
- 一个模块就是一个独立的文件,该文件内部的所有变量,外部无法获取
- 如果希望外部能够读取模块内部的某个变量或函数,就必须使用export关键字导出,在其他模块通过import引入后就可以在该模块中使用