Skip to content
导航栏

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")
}