ES6 核心模块
let & const
解构赋值
数组的解构赋值 对象的结构赋值 字符串的解构赋值 数值和布尔值的结构赋值 函数参数的结构赋值 圆括号问题
数组的扩展
对象的扩展
Proxy
Proxy 用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。简称“代理”
语法
let proxy = new Proxy(target, handler)
名称解释:
- target 表示所要拦截的对象
- handler 用来定制拦截行为的对象
拦截行为
- get(target, propKey, receiver) 拦截对象属性的读取,比如 proxy.foo 和 proxy['foo']
- set(target, propKey, value, receiver) 拦截对象属性的设置,比如 proxy.foo = v 或 proxy['foo'] = v,返回一个布尔值
- has(target, propKey) 拦截 propKey in proxy 的操作,返回一个布尔值
- ownKeys(target) 拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in 循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而 Object.keys()的返回结果仅包括目标对象自身的可遍历属性
- getOwnPropertyDescriptor(target, propKey) 拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象
- defineProperty(target, propKey, propDesc) 拦截 Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值
- preventExtensions(target) 拦截 Object.preventExtensions(proxy),返回一个布尔值
- getPrototypeOf(target) 拦截 Object.getPrototypeOf(proxy),返回一个对象
- isExtensible(target) 拦截 Object.isExtensible(proxy),返回一个布尔值
- setPrototypeOf(target, proto) 拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截
- apply(target, object, args) 拦截 Proxy 实例作为函数调用的操作,比如 proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)
- construct(target, args) 拦截 Proxy 实例作为构造函数调用的操作,比如 new proxy(...args)
- 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 函数就是一个普通函数,但是有两个特征:
- 一是,function 关键字与函数名之间有一个星号*
- 二是,函数内部使用 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 的本质区别:
- WeakSet 只能存储对象引用,不能存放值;而 Set 对象都可以存放
- 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 种)
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.species
- Symbol.match
- Symbol.replace
- Symbol.split
- Symbol.search
- Symbol.iterator
- Symbol.toPrimitive
- Symbol.toStringTag
- Symbol.unscopables