总结部分常用ES6的语法及其简单解析

let/const

let/const用于声明变量,替代老语法的var关键字,它的用法与var类似,但是所声明的变量只在所在的代码块中有效。

let/constvar的主要区别:

  • 不允许重复声明
  • 未定义就使用会报错:let/const不存在变量提升现象
  • 暂时性死区:在代码块内使用const命令let命令声明变量之前,该变量都不可用

const

let不相同的是,const声明的是一个只读常量。

const的特点:

  • constlet不同,const声明后必须立马赋值,只声明不赋值就会报错
  • const是一个只读常量,并不是变量的值不改变,而是变量指向的那个内存地址不改变。
    • 对于简单类型的数据(数值、字符串、布尔值),就相当于常量
    • 对于复合类型的数据(数组、对象),变量指向内存地址,const实际保存的是指向实际数据的指针,它只能保证指针不变,不能保证,指针里的内容不变,

解构赋值

多种解构

字符串解构

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';

数值和布尔值解构

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

对象解构

对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

形式:const { x, y } = { x: 1, y: 2 }

默认:const { x, y = 2 } = { x: 1 }

改名:const { x, y: z } = { x: 1, y: 2 }

数组解构

只要某种数据结构具有Iterator接口就可采用数组形式的解构赋值

形式:const [x, y] = [1, 2]

默认:const [x, y = 2] = [1]

函数参数解构

//数组参数解构
function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

//对象参数解构且有默认值
function move({x = 0, y = 0} = {}) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

应用场景

  • 交换变量值:[x, y] = [y, x]

  • 返回函数多个值:const [x, y, z] = Func()

  • 定义函数参数:Func([1, 2])

  • 提取JSON数据:const { name, version } = packageJson

  • 定义函数参数默认值:function Func({ x = 1, y = 2 } = {}) {}

  • 遍历Map结构:for (let [k, v] of Map) {}

  • 输入模块指定属性和方法:const { readFile, writeFile } = require("fs")

重点

  • 匹配模式:只要等号两边的模式相同,左边的变量就可以赋给右边
  • 解构赋值规则:只要右边不是对象或者数组,就会将其转换为对象
  • 解构不成功时,变量的值为undifined
  • undifinednull无法转为对象,因此无法赋值

箭头函数

ES6 允许使用箭头(=>)定义函数,简化定义函数

var f = v => v;

// 等同于
var f = function (v) {
  return v;
};
  • 无参数:() => {}
  • 单个参数:x => {}
  • 多个参数:(x, y) => {}
  • 解构参数:({x, y}) => {}

重点

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

数组的扩展

扩展运算符(...):转换数组为用逗号分隔的参数序列([...arr],相当于rest/spread参数的逆运算)

Array.from():转换具有Iterator接口的数据结构为真正数组,返回新数组

类数组对象:包含length的对象Arguments对象NodeList对象

可遍历对象:StringSet结构Map结构Generator函数

Array.of():转换一组值为真正数组,返回新数组

copyWithin():把指定位置的成员复制到其他位置,返回原数组

find():返回第一个符合条件的成员

findIndex():返回第一个符合条件的成员索引值

fill():根据指定值填充整个数组,返回原数组

keys():返回以索引值为遍历器的对象

values():返回以属性值为遍历器的对象

entries():返回以索引值和属性值为遍历器的对象

数组空位:ES6明确将数组空位转为undefined(空位处理规不一,建议避免出现)

扩展运算符的应用

克隆数组:const arr = [...arr1]

合并数组:const arr = [...arr1, ...arr2]

拼接数组:arr.push(...arr1)

代替apply:Math.max.apply(null, [x, y]) => Math.max(...[x, y])

转换字符串为数组:[..."hello"]

转换类数组对象为数组:[...Arguments, ...NodeList]

转换可遍历对象为数组:[...String, ...Set, ...Map, ...Generator]

与数组解构赋值结合:const [x, ...rest/spread] = [1, 2, 3]

计算Unicode字符长度:Array.from("hello").length => [..."hello"].length

Set

  • 定义:类似于数组的数据结构,成员值都是唯一且没有重复的值
  • 声明:const set = new Set(arr)
  • 入参:具有Iterator接口的数据结构
  • 属性
    • constructor:构造函数,返回Set
    • size:返回实例成员总数
  • 方法
    • add():添加值,返回实例
    • delete():删除值,返回布尔
    • has():检查值,返回布尔
    • clear():清除所有成员
    • keys():返回以属性值为遍历器的对象
    • values():返回以属性值为遍历器的对象
    • entries():返回以属性值和属性值为遍历器的对象
    • forEach():使用回调函数遍历每个成员

应用场景

  • 去重字符串:[...new Set(str)].join("")
  • 去重数组:[...new Set(arr)]Array.from(new Set(arr))
  • 集合数组
    • 声明:const a = new Set(arr1)const b = new Set(arr2)
    • 并集:new Set([...a, ...b])
    • 交集:new Set([...a].filter(v => b.has(v)))
    • 差集:new Set([...a].filter(v => !b.has(v)))
  • 映射集合
    • 声明:let set = new Set(arr)
    • 映射:set = new Set([...set].map(v => v * 2))set = new Set(Array.from(set, v => v * 2))

重点难点

  • 遍历顺序:插入顺序
  • 没有键只有值,可认为键和值两值相等
  • 添加多个NaN时,只会存在一个NaN
  • 添加相同的对象时,会认为是不同的对象
  • 添加值时不会发生类型转换(5 !== "5")
  • keys()values()的行为完全一致,entries()返回的遍历器同时包括键和值且两值相等

WeakSet

  • 定义:和Set结构类似,成员值只能是对象
  • 声明:const set = new WeakSet(arr)
  • 入参:具有Iterator接口的数据结构
  • 属性
    • constructor:构造函数,返回WeakSet
  • 方法
    • add():添加值,返回实例
    • delete():删除值,返回布尔
    • has():检查值,返回布尔

应用场景

  • 储存DOM节点:DOM节点被移除时自动释放此成员,不用担心这些节点从文档移除时会引发内存泄漏
  • 临时存放一组对象或存放跟对象绑定的信息:只要这些对象在外部消失,它在WeakSet结构中的引用就会自动消

重点难点

  • 成员都是弱引用,垃圾回收机制不考虑WeakSet结构对此成员的引用
  • 成员不适合引用,它会随时消失,因此ES6规定WeakSet结构不可遍历
  • 其他对象不再引用成员时,垃圾回收机制会自动回收此成员所占用的内存,不考虑此成员是否还存在于WeakSet结构

Map

  • 定义:类似于对象的数据结构,成员键是任何类型的值
  • 声明:const set = new Map(arr)
  • 入参:具有Iterator接口且每个成员都是一个双元素数组的数据结构
  • 属性
    • constructor:构造函数,返回Map
    • size:返回实例成员总数
  • 方法
    • get():返回键值对
    • set():添加键值对,返回实例
    • delete():删除键值对,返回布尔
    • has():检查键值对,返回布尔
    • clear():清除所有成员
    • keys():返回以键为遍历器的对象
    • values():返回以值为遍历器的对象
    • entries():返回以键和值为遍历器的对象
    • forEach():使用回调函数遍历每个成员

重点难点

  • 遍历顺序:插入顺序
  • 对同一个键多次赋值,后面的值将覆盖前面的值
  • 对同一个对象的引用,被视为一个键
  • 对同样值的两个实例,被视为两个键
  • 键跟内存地址绑定,只要内存地址不一样就视为两个键
  • 添加多个以NaN作为键时,只会存在一个以NaN作为键的值
  • Object结构提供字符串—值的对应,Map结构提供值—值的对应

WeakMap

  • 定义:和Map结构类似,成员键只能是对象
  • 声明:const set = new WeakMap(arr)
  • 入参:具有Iterator接口且每个成员都是一个双元素数组的数据结构
  • 属性
    • constructor:构造函数,返回WeakMap
  • 方法
    • get():返回键值对
    • set():添加键值对,返回实例
    • delete():删除键值对,返回布尔
    • has():检查键值对,返回布尔

应用场景

  • 储存DOM节点:DOM节点被移除时自动释放此成员键,不用担心这些节点从文档移除时会引发内存泄漏
  • 部署私有属性:内部属性是实例的弱引用,删除实例时它们也随之消失,不会造成内存泄漏

重点难点

  • 成员键都是弱引用,垃圾回收机制不考虑WeakMap结构对此成员键的引用
  • 成员键不适合引用,它会随时消失,因此ES6规定WeakMap结构不可遍历
  • 其他对象不再引用成员键时,垃圾回收机制会自动回收此成员所占用的内存,不考虑此成员是否还存在于WeakMap结构
  • 一旦不再需要,成员会自动消失,不用手动删除引用
  • 弱引用的只是键而不是值,值依然是正常引用
  • 即使在外部消除了成员键的引用,内部的成员值依然存在

Promise

  • 定义:Promise是一种异步编程的解决方案。从语法上来讲,Promise是一个对象,他可以获取异步操作的的消息。从本意上来讲,Promise是一个承诺,承诺过一段时间后给你一个结果。Promise有三种状态:pending(等待),fulfiled(成功),rejected(失败),状态一旦改变,就不会再变。
  • 状态:
    • 进行中:pending
    • 已成功:fulfilled
    • 已失败:rejected
  • 特点:
    • 对象的操作不受外界的影响
    • 一旦状态改变,任何时候都会得到这个结果
  • 示例:
const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
  • 出参

    • resolve:将状态从未完成变为成功,在异步操作成功时调用,并将异步操作的结果作为参数传递出去
    • reject:将状态从未完成变为失败,在异步操作失败时调用,并将异步操作的错误作为参数传递出去
  • 方法:

    • then():分别指定resolvedrejected状态的回调函数

      • 第一参数:状态变为resolved时调用
      • 第二参数:状态变为rejected时调用
    • catch():用于指定发生错误时的回调函数。

    • Promise.all():将多个实例包装成一个新实例,返回全部实例状态变更后的结果数组(齐变更再返回)

      • 入参:具有Iterator接口的数据结构
      • 成功:只有全部实例状态变成fulfilled,最终状态才会变成fulfilled
      • 失败:其中一个实例状态变成rejected,最终状态就会变成rejected
    • Promise.race():将多个实例包装成一个新实例,返回全部实例状态优先变更后的结果(先变更先返回)

      • 入参:具有Iterator接口的数据结构
      • 成功失败:哪个实例率先改变状态就返回哪个实例的状态
    • Promise.resolve():将对象转为Promise对象(等价于new Promise(resolve => resolve()))

      • Promise实例:原封不动地返回入参
      • Thenable对象:将此对象转为Promise对象并返回(Thenable为包含then()的对象,执行then()相当于执行此对象的then())
      • 不具有then()的对象:将此对象转为Promise对象并返回,状态为resolved
      • 不带参数:返回Promise对象,状态为resolved
    • Promise.reject():将对象转为状态为rejected的Promise对象(等价于new Promise((resolve, reject) => reject()))

应用场景

  • 加载图片

  • AJAX转Promise对象

重点难点

  • 只有异步操作的结果可决定当前状态是哪一种,其他操作都无法改变这个状态

  • 状态改变只有两种可能:从pending变为resolved、从pending变为rejected

  • 一旦新建Promise对象就会立即执行,无法中途取消

  • 不设置回调函数,内部抛错不会反应到外部

  • 当处于pending时,无法得知目前进展到哪一个阶段

  • 实例状态变为resolvedrejected时,会触发then()绑定的回调函数

  • resolve()reject()的执行总是晚于本轮循环的同步任务

  • then()返回新实例,其后可再调用另一个then()

  • then()运行中抛出错误会被catch()捕获

  • reject()的作用等同于抛出错误

  • 实例状态已变成resolved时,再抛出错误是无效的,不会被捕获,等于没有抛出

  • 实例状态的错误具有冒泡性质,会一直向后传递直到被捕获为止,错误总是会被下一个catch()捕获

  • 不要在then()里定义rejected状态的回调函数(不使用其第二参数)

  • 建议使用catch()捕获错误,不要使用then()第二个参数捕获

  • 没有使用catch()捕获错误,实例抛错不会传递到外层代码,即不会有任何反应

  • 作为参数的实例定义了catch(),一旦被rejected并不会触发Promise.all()catch()

  • Promise.reject()的参数会原封不动地作为rejected的理由,变成后续方法的参数

for...of循环

  • 定义:调用Iterator接口产生遍历器对象(for-of内部调用数据结构的Symbol.iterator())

  • 遍历字符串for-in获取索引for-of获取.

  • 遍历数组for-in获取索引for-of获取

  • 遍历Setfor-of获取 => for (const v of set)

  • 遍历Mapfor-of获取键值对 => for (const [k, v] of map)for-of获得到的是一个由构成的数组

    let map = new Map().set('a', 1).set('b', 2);
    for (let pair of map) {
      console.log(pair);
    }
    // ['a', 1]
    // ['b', 2]
    
    for (let [key, value] of map) {
      console.log(key + ' : ' + value);
    }
    // a : 1
    // b : 2
    
  • 遍历对象for-in获取for-of需自行部署for-of并不能直接遍历对象,如果直接遍历会报错。我们需要部署Iterator接口。遍历对象还是使用for-in更好一点

    1. 使用Object.keys方法将对象的键名生成一个数组,然后遍历这个数组。
    for (var key of Object.keys(someObject)) {
      console.log(key + ': ' + someObject[key]);
    }
    
    1. 使用 Generator 函数将对象重新包装一下。
    function* entries(obj) {
      for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
      }
    }
    
    for (let [key, value] of entries(obj)) {
      console.log(key, '->', value);
    }
    // a -> 1
    // b -> 2
    // c -> 3
    
  • for-in区别

    • 有着同for-in一样的简洁语法,但不会像for-in一样会遍历原型上的属性。
    • for-of会以添加顺序来进行遍历,而不会像for-in以任意顺序遍历
    • 不同于forEach(),它可与breakcontinuereturn配合使用
    • 提供遍历所有数据结构的统一操作接口

搬运文章

ES6入门教程

Promise不会??看这里!!!史上最通俗易懂的Promise!!!

近一万字的ES6语法知识点补充

posted @ 2020-08-12 11:37  ChunCode  阅读(72)  评论(0编辑  收藏  举报