ES6 核心模块

let & const

解构赋值

数组的解构赋值 对象的结构赋值 字符串的解构赋值 数值和布尔值的结构赋值 函数参数的结构赋值 圆括号问题

数组的扩展

对象的扩展

Proxy

Proxy 用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。简称“代理”

语法

let proxy = new Proxy(target, handler)

名称解释:

  1. target 表示所要拦截的对象
  2. handler 用来定制拦截行为的对象

拦截行为

  1. get(target, propKey, receiver) 拦截对象属性的读取,比如 proxy.foo 和 proxy['foo']
  2. set(target, propKey, value, receiver) 拦截对象属性的设置,比如 proxy.foo = v 或 proxy['foo'] = v,返回一个布尔值
  3. has(target, propKey) 拦截 propKey in proxy 的操作,返回一个布尔值
  4. ownKeys(target) 拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in 循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而 Object.keys()的返回结果仅包括目标对象自身的可遍历属性
  5. getOwnPropertyDescriptor(target, propKey) 拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象
  6. defineProperty(target, propKey, propDesc) 拦截 Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值
  7. preventExtensions(target) 拦截 Object.preventExtensions(proxy),返回一个布尔值
  8. getPrototypeOf(target) 拦截 Object.getPrototypeOf(proxy),返回一个对象
  9. isExtensible(target) 拦截 Object.isExtensible(proxy),返回一个布尔值
  10. setPrototypeOf(target, proto) 拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截
  11. apply(target, object, args) 拦截 Proxy 实例作为函数调用的操作,比如 proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)
  12. construct(target, args) 拦截 Proxy 实例作为构造函数调用的操作,比如 new proxy(...args)
  13. deleteProperty(target, propKey) 拦截 delete proxy[propKey]的操作,返回一个布尔值

Reflect

Iterator

Iterator 迭代器就是一个接口方法,它为不同的数据结构提供了一个统一的访问机制;使得数据结构的成员能够按某种次序排列,并逐个被访问。

var it = makeIterator(['a', 'b'])
it.next() // { value: 'a', done: false }
it.next() // { value: 'b', done: false }
it.next() // { value: undefined, done: true }

function makeIterator(arr) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < arr.length ?
        { value: arr[nextIndex++], done: false },
        { value: undefined, done: true }
    }
  }
}

makeIterator 函数,它就是一个迭代器生成函数,作用就是返回一个迭代器对象。对数组执行这个函数,就会返回该数组的迭代器对象 it。通过调用 next 函数,返回 value 和 done 两个属性;value 属性返回当前位置的成员,done 属性是一个布尔值,表示遍历是否结束,即是否还有必要再一次调用 next 方法;当 done 为 true 时,即遍历完成。

如何让一个对象成为一个可迭代对象呢?

Iterator 规范————Iterator 迭代器包含一个 next()方法,方法调用返回返回两个属性:done 和 value;通过定义一个对象的 Symbol.iterator 属性,即可将此对象修改为迭代器对象,支持 for...of 遍历。

  • Generator 函数就是一个普通函数,但是有两个特征:
    1. 一是,function 关键字与函数名之间有一个星号*
    2. 二是,函数内部使用 yield 表达式,定义不同的内部状态

Generator 函数执行后,会返回一个 Iterator 对象。

总结:Generator(生成器)可以理解为是对 Iterator(迭代器)的一种实现。

Iterator 应用

Generator(生成器)就是其中最典型的一个应用,当然还有其他,例如:Map、Set、Array 等原生具备 Iterator(迭代器),支持 for...of 循环。

Object 实现 Iterator 接口

Object 对象虽然不支持 Iterator(迭代器),但我们可以使用 Generator(生成器)进行包装。

let obj = { a: 1, b: 2, c: 3 }
function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]]
  }
}

for (let [key, value] of entries(obj)) {
  console.log(key, '--->', value)
}

Set & WeakSet

Set 是一种叫做 集合 的数据结构,类似于数组,但成员是唯一且无序的,没有重复的值

语法:new Set([iterable])

以下是 Set 实例的属性和方法

名称 意思
constructor 构造函数,默认就是 Set 函数
size 返回 Set 实例的成员总数
add 添加某个值,返回 Set 结构本身
size 返回 Set 实例的成员总数
delete 删除某个值,返回一个布尔值,表示删除是否成功
has 返回一个布尔值,表示该值是否为 Set 的成员
clear 清除所有成员,没有返回值
size 清除所有成员,没有返回值
keys 返回键名的遍历器
values 返回键值的遍历器
entries 返回键值对的遍历器
forEach 使用回调函数遍历每个成员
const set = new Set()
console.log(set.constructor) // [Function: Set]
set
  .add(1)
  .add(2)
  .add(2)
console.log(set.size) // 2
console.log(set.has(1), set.has(3)) // true false
console.log(set.keys()) // [Set Iterator] { 1, 2 }
console.log(set.values()) // [Set Iterator] { 1, 2 }
console.log(set.entries()) // [Set Iterator] { 1, 2 }
set.forEach((item) => {
  console.log(item) // 1 2
})
console.log(set.delete(1)) // true
console.log(set.clear()) // undefined
console.log(set) // Set {}

// 转换成真实数组
const set = new Set([1, 2, 3, 4])
const arr = [...set] // 剩余参数转换成数组
const arr1 = Array.from(set) // Array.from方法转换成数组
console.log(set) // Set { 1, 2, 3, 4 }
console.log(arr) // [ 1, 2, 3, 4 ]
console.log(arr1) // [ 1, 2, 3, 4 ]

// 数组去重
const set = new Set([1, 2, 3, 4, 5, 3, 2])
console.log([...set]) // [ 1, 2, 3, 4, 5 ]

WeakSet 对象允许你将 弱引用对象 储存在一个集合中

WeakMap 没有 size 属性,不可遍历(弱引用类型)

WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏

  • WeakSet 与 Set 的本质区别:
  1. WeakSet 只能存储对象引用,不能存放值;而 Set 对象都可以存放
  2. WeakSet 对象中存储的对象值都是被弱引用的,即垃圾回收机制不考虑 WeakSet 对该对象的引用

Map & WeakMap

Map 是一种叫做 字典 的数据结构

不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作 Map 构造函数的参数。这就是说,Set 和 Map 都可以用来生成新的 Map

Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应

注意:Set 和 Map 注意的应用场景在于 数组去重数据存储

Symbol

Symbol 基本数据类型, 独一无二的类型【一般作为对象的 key】

扩展:基本数据类型:string number boolean null undefined symbol bigint

// 基本使用
let s1 = Symbol('tmc')
let s2 = Symbol('tmc')
console.log(s1 === s2) // false
let obj = {
  name: 'tmc',
  age: 12,
  [s1]: 'ok',
}
  • 遍历(Symbol 属性默认是不能枚举的)
for (let key in obj) {
  console.log(key)
}
console.log(Object.keys(obj))
console.log(Object.getOwnPropertyNames(obj))
console.log(JSON.stringify(obj))
// 注意:以上四种方式都不能遍历symbol属性
console.log(Object.getOwnPropertySymbols(obj))
console.log(Reflect.ownKeys(obj))
// 注意:以上两种可以返回symbol
  • 两个静态方法 for keyFor
const s22 = Symbol.for('tmc') // 声明全新的
const s23 = Symbol.for('tmc') // 把之前的拿过来用
// console.log(s22 === s23) true
// 注意:包含(当前页面,iframe等)
  • 元编程能力 -> 改写语法本身(11 种)
  1. Symbol.hasInstance
  2. Symbol.isConcatSpreadable
  3. Symbol.species
  4. Symbol.match
  5. Symbol.replace
  6. Symbol.split
  7. Symbol.search
  8. Symbol.iterator
  9. Symbol.toPrimitive
  10. Symbol.toStringTag
  11. Symbol.unscopables