ES6

数据类型

  • number、boolean、string、null、undefined

  • Object(ArrayFunctionDateRegExpError))

  • Symbol、BigInt

const、let、块级作用域{}

  • 不允许重复声明

  • 不存在变量提升

  • 暂时性死区

字符串扩展

- includes
- repeat
- startWith
- endWith

模板字符串

==解构赋值==

  • 解构不成功undefined

  • 解构赋值规则:只要等号右边的值不是对象或数组,就先将其转为对象,undefinednull无法转为对象,因此无法进行解构

  • 字符串解构:const [a, b, c, d, e] = "hello"

  • 数值解构:const { toString: s } = 123

  • 布尔解构:const { toString: b } = true

  • 对象解构

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

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

    • 重命名:const { x, y: z } = { x: 1, y: 2 }

    • ;({ name: user.name, email: user.email, ...userDetails } = obj)

  • 数组解构

    const csvFileLine = '1997,John Doe,US,john@doe.com,New York'
    const { 2: country, 4: state } = csvFileLine.split(',')
  • 函数参数解构

    • function Func([x = 0, y = 1]) {}

    • function Func({ x = 0, y = 1 } = {}) {}

  • 应用场景

    • 排除对象不需要的属性:const {prop1, prop2, ...otherProps} = obj

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

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

    • 定义函数参数:

      • Func([1, 2]){} 数组有序

      • Func({x, y, z}) {} 对象可无序

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

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

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

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

for of 可迭代对象原理Symbol.iterator

Iterator

数值扩展

  • Number.EPSILON

  • Number.MIN_SAFE_INTEGER

  • Number.MAX_SAFE_INTEGER

  • Number.parseInt()

  • Number.parseFloat()

  • Number.isFinite()

  • Number.isNaN()

  • Number.isInteger()

  • Number.isSafeInteger()

对象扩展

  • 简洁表示

  • 属性名可使用表达式

  • API

    • Object.is()

    • Object.assign()

    • Object.keys()、Object.values()、Object.entries()

    • Object.getPrototypeOf()

    • Object.setPrototypeOf()

    • Object.getOwnPropertyDescriptors()

    • Object.entries()

    • Object.fromEntries()

  • 属性遍历

    • for-in

    • Object.keys()、Object.values()

    • Object.getOwnPropertyNames()

    • Object.getOwnPropertySymbols()

    • Reflect.ownKeys()

      • 规则

        • 首先遍历所有数值键,按照数值升序排列

        • 其次遍历所有字符串键,按照加入时间升序排列

        • 最后遍历所有Symbol键,按照加入时间升序排列

  • 链判断操作符(?.):是否存在对象属性(不存在返回undefined且不再往下执行)

    • 对象属性:obj?.prop、obj?.[expr]

    • 函数调用:func?.(...args)

  • 空判断操作符(??):是否值为 undefined 或 null,是则使用默认值

数组扩展

==扩展运算符(...)==

  • 浅克隆数组(对象):const arr = [...arr1]

  • 浅合并数组(对象):const arr = [...arr1, ...arr2]

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

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

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

  • 转换字符串为对象:{ ..."hello" }

  • 转换数组为对象:{ ...[1, 2] }

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

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

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

  • 对象克隆(同Object.assign):const objCopy = { ...obj, ...objOthers }

  • 与对象解构赋值结合:const { x, ...rest } = { x: 1, y: 2, z: 3 }

  • 修改现有对象部分属性:const obj = { x: 1, ...{ x: 2 } }

API

  • Array.from()

  • Array.isArray

  • Array.of()

  • keys()、values()、entries() 返回遍历器对象,可用for-of自动遍历或next()手动遍历

  • includes()

  • fill()

  • find()、findIndex()

  • flat()

==函数扩展==

参数默认值

  • 指定某个参数不能省略

rest/spread 剩余参数

箭头函数

  1. 没有 this,函数体里面的 this 是箭头函数定义时所在对象,不是运行时(this 看上一级,若上级是箭头函数继续往上找), 作用域是栈内存不是堆内存

  2. 不能改变this绑定,即使通过call、apply、bind

  3. 不能用作构造函数

  4. 没有原型对象

  5. 没有自己的 super 和 new.target 绑定

  6. 没有 arguments,但有...

  7. 形参名称不能重复

  8. 返回对象时必须在对象外面加上括号

  9. 不可用 yield,因此不能用 Generator 函数

Symbol

Set

  • 去重字符串:[...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)))

  • WeakSet

  • 遍历顺序:插入顺序

  • 添加多个NaN时,只会存在一个NaN

  • 添加相同的对象时,会认为是不同的对象

Map

  • 遍历顺序:插入顺序

  • 添加多个以NaN作为键时,只会存在一个以NaN作为键的值

  • Object结构提供字符串—值的对应,Map结构提供值—值的对应

==Promise==(见实现)

Proxy & Reflect

  • 定义:修改某些操作的默认行为

==Class==

1 class声明会提升,但不会初始化赋值,类似const、let`

2 class内部默认严格模式

3 class的所有方法(包括静态方法和实例方法)都是不可枚举的

4 class的所有方法(包括静态方法和实例方法)都没有原型对象prototype

5 必须使用new调用class

6 class内部无法重写类名

  • constructor

    • ES5 实质:先创造子类实例的 this,再将父类的属性方法添加到 this 上Parent.apply(this)

    • ES6 实质:先将父类实例的属性方法加到 this 上(调用 super()),再用子类构造函数修改 this

  • extends

  • super

    • 在普通方法中指向父类的原型对象,在静态方法中指向父类

  • static

  • ==class有两条原型链==

    • Child.__proto__ === Parent //核心目的是实现静态方法继承

    • Child.prototype.__proto__ === Parent.prototype

  • new.target

==Module==

  • export

    • 默认导出:export default Person(导入时可指定模块任意名称,无需知晓内部真实名称,只能使用一次)

    • 单独导出:export const name = "Jack"

    • 按需导出:export { age, name, sex }(推荐)

    • 改名导出:export { name as newName }

  • import

    • 默认导入:import anyName from "module1"

    • 整体导入:import * as Person from "module1"

    • 按需导入:import { age, name, sex } from "module1"

    • 改名导入:import { xxx, name as newName} from "module1"

    • 自执导入:import "module1"

    • 引入文件:import "xxxx.js"

    • 复合导入:import anyName, { name } from "module1"

  • 复合模式

  • CommonJS(同步) vs ESM(浏览器、服务器)

    • 导出方式不同

      • 具名导出/导入: Named Import/Export

      • 默认导出/导入: Default Import/Export

    • 动态依赖与静态依赖(export/import 提升,必须定义在顶层):前者建立模块依赖关系是在运行时,后者是在编译时

      • require的模块路径可以动态指定,支持传入一个表达式,甚至可以通过if语句判断是否加载某个模块

    • 输出值得拷贝 vs 输出值得引用(read-only)

    • 都可解决循环依赖

      • CommonJS使用的是模块缓存

        • 对应值得拷贝 -> 开辟新的内存

      • ESM使用的模块记录

    • CommonJS的export和module.export指向同一块内存,但由于最后导出的是module.export,所以不能直接给export赋值,会导致指向丢失

    • CommonJS查找模块时,核心模块和文件模块的查找都比较简单,对于react/vue这种第三方模块,会从当前目录下的node_module文件下开始,递归往上查找,找到该包后,根据package.json的main字段找到入口文件

  • 加载实现

    • 传统加载

      • 同步加载:<script src=""></script>

      • defer 异步加载:<script src="" defer></script>(顺序加载,渲染完再执行)

      • async 异步加载:<script src="" async></script>(乱序加载,下载完就执行)

    • 模块加载:<script type="module" src=""></script>(默认是defer加载)

  • import():动态导入

    • require()同步加载,import()异步加载

    • 按需加载、条件加载、模块路径动态化

Last updated