ES6
数据类型
number、boolean、string、null、undefined
Object(
Array、Function、Date、RegExp、Error))Symbol、BigInt
const、let、块级作用域{}
不允许重复声明
不存在变量提升
暂时性死区
字符串扩展
- includes
- repeat
- startWith
- endWith模板字符串
==解构赋值==
解构不成功
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)
数组解构
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 剩余参数
箭头函数
没有 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的所有方法(包括静态方法和实例方法)都没有原型对象prototype5 必须使用
new调用class6
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