前端重点梳理(三):JS进阶和ES6新增语法

63 阅读7分钟

异步


同步和异步: JS是单线程语言,同步会阻塞后面代码的执行,因此引入了异步

微任务和宏任务:

  • 微任务:Promise.then、async、await
  • 宏任务:setTimeout、setInterval、Ajax

事件循环机制(eventloop):

  1. 所有同步任务都在主线程上依次执行,形成一个执行栈(调用栈),异步任务则放入一个任务队列
  2. 从上到下,先将遇到的所有同步任务依次压入执行栈中执行,遇到微任务加到微任务队列中,遇到宏任务加到红任务队列中
  3. 执行完同步任务,取出微任务队列中的微任务执行其同步代码,遇到微任务添添加到微任务队列末尾,遇到宏任务添加到宏任务队列末尾,继续执行,把微任务全部执行完
  4. 微任务执行完后,取出宏任务队列中的宏任务执行其同步代码,遇到微任务添加到微任务队列末尾,遇到宏任务添加到宏任务队列末尾
  5. 每次执行完一个宏任务都去检查微任务队列是否有新的微任务,如果有,执行所有微任务后再继续执行宏任务
  6. 如此循环,直到执行完所有宏任务

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:
  1. Promise.prototype.then: then方法在promise执行结束后被调用,返回一个Promise对象
    链式调用:只要状态改变就会一直调用then方法,可以通过返回一个pending状态的Promise对象中断链式调用
  2. Promise.prototype.catch: catch方法是then方法的语法糖, 可以只在最后指定的失败的回调
    前面任何操作出了异常, 都会通过异常穿透传到最后失败的回调中处理
  3. Promise.all 参数为包含 n 个 promise 的数组 ,返回一个新的Promise对象
    新Promise对象的结果:所有promise都成功才为成功,只要有一个失败就为失败
  4. Promise.race 参数为包含 n 个 promise 的数组 ,返回一个新的Promise对象
    新Promise对象的结果:第一个完成(最先改变状态)的promise的状态和结果

async 和 await


async:
  1. 作用:把一个有返回值的函数封装为一个Promise对象
  2. Promise对象的结果由 async 函数的返回值决定:
    如果返回值为非Promise类型,promise的状态为成功,结果为返回值
    如果返回值为Promise类型,promise的状态和结果为返回值promise的状态和结果
    如果抛出异常,promise的状态为失败,结果为抛出的异常
await 表达式:
  1. 作用:接收成功的Promise对象的结果
  2. await 右侧的表达式一般为Promise对象,但也可以为其他值 如果是成功的Promise对象,await 返回的是该Promise对象的结果值 如果是失败的Promise对象,会抛出异常,需要通过 try...catch 进行捕获 如果是其他值,则直接将该值作为 await 的返回值
  3. await 必须写在 async 函数中,但 async 函数可以没有 await
JS继承
  1. 原型继承:将子类的prototype设置为父类的实例,继承到父类原型中的属性和方法
  2. 借用构造函数:在子类构造函数内部使用call或apply来调用父类构造函数,继承到父类的实例属性和方法
  3. 组合继承:将原型链继承与构造函数继承组合在一起
  4. class继承:extends + super
  5. 寄生式继承
  6. 寄生式组合继承

ES6 新增语法


const 和 let 关键字:

  1. const 用于声明常量且声明时必须进行赋值,let 用于声明变量
  2. const 和 let 具有块级作用域,不存在变量提升
  3. 存在暂时性死区,即如果块级作用域的内部外部有同名变量,在块级作用域中不会再访问外部的变量

新增数据类型: Symbol 和 BigInt

  • Symbol:代表独一无二的值,最大的用法是用来定义对象的唯一属性名。
  • BigInt:可以表示任意大小的整数。

变量的解构赋值: 将数组或对象中的值提取出来,一 一对应地赋值给变量

扩展运算符(...):

  • 可以将数组进行拆解
  • 用法:合并数组,函数接收不定量参数

模板字符串(反引号``):

  1. 可以解析变量,通过 ${变量名} 使变量可以直接随字符串一起输出
  2. 可以识别回车换行
  3. 可以通过 ${fun} 调用函数
箭头函数
  1. 箭头函数没有自己的this指向,而是使用上下文的this,因此this指向不能被改变
  2. 箭头函数没有原型属性 prototype
  3. 基于以上两点,箭头函数不能作为构造函数,不能使用new关键字
  4. 箭头函数没有arguments,可以使用
Promise
async await
class 类
  • 类的性质:
  1. class 的本质还是 function
  2. 类有一个默认的构造器方法constructor ,通过 new 命令生成对象实例时自动调用该方法
  3. 类的数据类型就是函数,类本身就指向构造函数 。
  4. 类的所有方法都定义 在类的 prototype 属性上
  5. 变量名前加#表示私有属性,方法名前加_表示私有方法
  6. 类内部的 this 指向类的实例 ,通过 this 定义的属性是定义在实例对象上的,否则都是定义在原型上
  • 类的继承: extends + super
Set 和 Map 数据结构
  • Set:
    允许存储任何类型的值,类似于数组,但是成员的值都是唯一的,没有重复的值
  1. add() 增加值
  2. has() 查询
  3. size属性 取得元素数量
  4. delete()clear() 删除元素
  • Map:
    保存键值对, 任何类型的值都可以作为键或值,构造函数Map可以接受一个数组作为参数
  1. set() 方法添加键/值对
  2. get() 和 has() 进行查询
  3. size属性 获取映射中的键/值对的数量
  4. delete()clear() 删除值
  • WeakMap:
  1. 弱映射:弱映射中的只能是**Object**或者继承自 Object 的类型
  2. 作用:实现真正私有变量的一种新方式。私有变量会存储在弱映射中,以对象实例为键,以私有成员的字典为值
  • WeakSet:
  1. WeakSet 的成员只能是对象,而不能是其他类型的值
  2. WeakSet 不可遍历
Proxy/Reflect
  • 代理是目标对象的抽象,它可以用作目标对象的替身,但又完全独立于目标对象。
  • 可以通过捕获器对基本操作进行拦截并修改。
  • Reflect 对象的方法与 Proxy 对象的方法 一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就使 Proxy 对象可以方便地调用对应的 Reflect 方法来完成默认行为,作为修改行为
ES6模块化 Module
  • 一个模块就是一个独立的文件,该文件内部的所有变量,外部无法获取
  • 如果希望外部能够读取模块内部的某个变量或函数,就必须使用export关键字导出,在其他模块通过import引入后就可以在该模块中使用