ES6
数据类型
number、boolean、string、null、undefined
Object(
Array
、Function
、Date
、RegExp
、Error
))Symbol、BigInt
const、let、块级作用域{}
不允许重复声明
不存在变量提升
暂时性死区
字符串扩展
模板字符串
==解构赋值==
解构不成功
undefined
解构赋值规则:只要等号右边的值不是对象或数组,就先将其转为对象,
undefined
和null
无法转为对象,因此无法进行解构字符串解构:
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)
数组解构
函数参数解构
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 剩余参数
箭头函数
没有 this,函数体里面的 this 是箭头函数定义时所在对象,不是运行时(this 看上一级,若上级是箭头函数继续往上找), 作用域是栈内存不是堆内存
不能改变this绑定,即使通过call、apply、bind
不能用作构造函数
没有原型对象
没有自己的 super 和 new.target 绑定
没有 arguments,但有...
形参名称不能重复
返回对象时必须在对象外面加上括号
不可用 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