08_es6&es7知识
1. let/const/var
1.1 let/const
- let/const是没有变量提升的
- 每次执行上下文会关联到一个变量环境(VariableEnvironment)中, 再执行代码中变量和函数的声明会作为环境记录添加到变量环境中
- 使用let/const声明变量, 变量会被保存到
VariableMap
中, 本质上c++
实现的hashMap
, 为了方便后续对变量的查找.
1.2 块级作用域
- 形成块级作用域条件(对于var声明无效)
- {}
- if
- switch
- for循环
2. 标签模板字符串
- 作用地点
- React中css书写方式style component
js
// 第一个参数依然是模块字符串中整个字符串, 只是被切成多块,放到了一个数组中
// 第二个参数是模块字符串中, 第一个 ${}
function foo(m, n, x) {
console.log(m, n, x, '---------')
}
// foo("Hello", "World")
// 另外调用函数的方式: 标签模块字符串
// foo``
// foo`Hello World`
const name = "why"
const age = 18
// ['Hello', 'Wo', 'rld']
foo`Hello${name}Wo${age}rld`
3. 展开语法
3.1 ...展开语法
- 展开语法为浅拷贝
js
const names = ["abc", "cba", "nba"]
const name = "why"
const info = {name: "why", age: 18}
// 1.函数调用时
function foo(x, y, z) {
console.log(x, y, z)
}
// foo.apply(null, names)
foo(...names)
foo(...name)
// 2.构造数组时
const newNames = [...names, ...name]
console.log(newNames)
// 3.构建对象字面量时ES2018(ES9)
const obj = { ...info, address: "广州市", ...names }
console.log(obj)
3.2 大数值
- 进制
js
const num1 = 10 // 十进制
const num2 = 0b10 // 二进制
const num8 = 0o10 // 八进制
const num16 = 0x10 // 十六进制
- 大数值连接符
js
1_000_000_000 // 方便阅读
3.3 Symbol
- 作用: 为对象添加独一无二的属性名
- 语法:
Symbol([description])
description是可选的, 用于描述Symbol属性的字符串
js
const s1 = Symbol("kobe")
const s2 = Symbol("kobe")
console.log(s1 === s2) // false
- getOwnPropertySymbols: 获取对象中所有的Symbol属性名
js
const info = {
[s1]: "kobe",
[s2]: "kobe",
name: "why",
age: 18
}
const sKeys = Object.getOwnPropertySymbols(info)
for(const sKey of sKeys) {
console.log(info[sKey])
}
- Symbol.for: 通过Symbol.for()获取Symbol值, 如果之前有, 则直接返回, 如果没有, 则创建一个新的Symbol值
js
const s1 = Symbol.for("kobe")
const s2 = Symbol.for("kobe")
console.log(s1 === s2) // true
const key = Symbol.keyFor(s1)
console.log(key) // kobe
const sc = Symbol.for(key)
console.log(sc === s1) // true
4. Set/WeakSet
4.1 Set
- Set是一种数据结构, 用来表示集合
- Set中的元素是唯一的, 没有重复的值
- Set中的元素是有序的
- Set中的元素可以是任意类型的
- Set中的元素可以通过for...of遍历
- Set中的元素可以通过size属性获取
- Set中的元素可以通过add方法添加
- Set中的元素可以通过delete方法删除
- Set中的元素可以通过clear方法清空
- Set中的元素可以通过has方法判断是否存在
- Set中的元素可以通过forEach方法遍历
- Set中的元素可以通过Array.from方法转换成数组
js
// 10, 20, 40, 333
// 1.创建Set结构
const set = new Set()
set.add(10)
set.add(20)
set.add(40)
set.add(333)
set.add(10)
// 2.添加对象时特别注意:
set.add({})
set.add({})
const obj = {}
set.add(obj)
set.add(obj)
// console.log(set)
// 3.对数组去重(去除重复的元素)
const arr = [33, 10, 26, 30, 33, 26]
// const newArr = []
// for (const item of arr) {
// if (newArr.indexOf(item) !== -1) {
// newArr.push(item)
// }
// }
const arrSet = new Set(arr)
// const newArr = Array.from(arrSet)
// const newArr = [...arrSet]
// console.log(newArr)
// 4.size属性
console.log(arrSet.size)
// 5.Set的方法
// add
arrSet.add(100)
console.log(arrSet)
// delete
arrSet.delete(33)
console.log(arrSet)
// has
console.log(arrSet.has(100))
// clear
// arrSet.clear()
console.log(arrSet)
// 6.对Set进行遍历
arrSet.forEach(item => {
console.log(item)
})
for (const item of arrSet) {
console.log(item)
}
4.2 WeakSet
- WeakSet是一种数据结构, 用来表示集合
- 是弱引用, 当一个对象作为WeakSet的元素时, 如果后续主动将对象设置为null,那么GC会自动回收该对象
- 只能存储对象类型
js
const weakSet = new WeakSet()
// 1.区别一: 只能存放对象类型
// TypeError: Invalid value used in weak set
// weakSet.add(10)
// 强引用和弱引用的概念(看图)
// 2.区别二: 对对象是一个弱引用
let obj = {
name: "why"
}
// weakSet.add(obj)
const set = new Set()
// 建立的是强引用
set.add(obj)
// 建立的是弱引用
weakSet.add(obj)
// 3.WeakSet的应用场景
const personSet = new WeakSet()
class Person {
constructor() {
personSet.add(this)
}
running() {
if (!personSet.has(this)) {
throw new Error("不能通过非构造方法创建出来的对象调用running方法")
}
console.log("running~", this)
}
}
let p = new Person()
p.running()
p = null
p.running.call({name: "why"})
5. Map/WeakMap
5.1 Map
- Map是一种数据结构, 用来表示映射表
- Map中的key是唯一的, 没有重复的值
- Map中key是key扩展的, 可以是任意类型的,而非对象类型的key都会被转换成字符串类型
js
// 1.JavaScript中对象中是不能使用对象来作为key的
const obj1 = { name: "why" }
const obj2 = { name: "kobe" }
// const info = {
// [obj1]: "aaa",
// [obj2]: "bbb"
// }
// console.log(info)
// 2.Map就是允许我们对象类型来作为key的
// 构造方法的使用
const map = new Map()
map.set(obj1, "aaa")
map.set(obj2, "bbb")
map.set(1, "ccc")
console.log(map)
const map2 = new Map([[obj1, "aaa"], [obj2, "bbb"], [2, "ddd"]])
console.log(map2)
// 3.常见的属性和方法
console.log(map2.size)
// set
map2.set("why", "eee")
console.log(map2)
// get(key)
console.log(map2.get("why"))
// has(key)
console.log(map2.has("why"))
// delete(key)
map2.delete("why")
console.log(map2)
// clear
// map2.clear()
// console.log(map2)
// 4.遍历map
map2.forEach((item, key) => {
console.log(item, key)
})
for (const item of map2) {
console.log(item[0], item[1])
}
for (const [key, value] of map2) {
console.log(key, value)
}
5.2 WeakMap
- WeakMap是一种数据结构, 用来表示映射表
- WeakMap不可以用基本数据类型作为键值(这点和Map是有所区别的)
js
const obj = {name: "obj1"}
// 1.WeakMap和Map的区别二:
const map = new Map()
map.set(obj, "aaa")
const weakMap = new WeakMap()
weakMap.set(obj, "aaa")
// 2.区别一: 不能使用基本数据类型
// weakMap.set(1, "ccc")
// 3.常见方法
// get方法
console.log(weakMap.get(obj))
// has方法
console.log(weakMap.has(obj))
// delete方法
console.log(weakMap.delete(obj))
// WeakMap { <items unknown> }
console.log(weakMap)
5.3 WeakMap响应式原理中使用
js
// 应用场景(vue3响应式原理)
const obj1 = {
name: "why",
age: 18
}
function obj1NameFn1() {
console.log("obj1NameFn1被执行")
}
function obj1NameFn2() {
console.log("obj1NameFn2被执行")
}
function obj1AgeFn1() {
console.log("obj1AgeFn1")
}
function obj1AgeFn2() {
console.log("obj1AgeFn2")
}
const obj2 = {
name: "kobe",
height: 1.88,
address: "广州市"
}
function obj2NameFn1() {
console.log("obj1NameFn1被执行")
}
function obj2NameFn2() {
console.log("obj1NameFn2被执行")
}
// 1.创建WeakMap
const weakMap = new WeakMap()
// 2.收集依赖结构
// 2.1.对obj1收集的数据结构
const obj1Map = new Map()
obj1Map.set("name", [obj1NameFn1, obj1NameFn2])
obj1Map.set("age", [obj1AgeFn1, obj1AgeFn2])
weakMap.set(obj1, obj1Map)
// 2.2.对obj2收集的数据结构
const obj2Map = new Map()
obj2Map.set("name", [obj2NameFn1, obj2NameFn2])
weakMap.set(obj2, obj2Map)
// 3.如果obj1.name发生了改变
// Proxy/Object.defineProperty
obj1.name = "james"
const targetMap = weakMap.get(obj1)
const fns = targetMap.get("name")
fns.forEach(item => item())
6. es7中的新特性
6.1 Array.prototype.includes
- includes方法: 对比indexOf方法, 可以判断
NAN
是否存在
js
const names = ["abc", "cba", "nba", "mba", NaN]
if (names.indexOf("cba") !== -1) {
console.log("包含abc元素")
}
// ES7 ES2016
if (names.includes("cba", 2)) {
console.log("包含abc元素")
}
if (names.indexOf(NaN) !== -1) {
console.log("包含NaN")
}
if (names.includes(NaN)) {
console.log("包含NaN")
}