1 symbol
ES6 新增的基本数据类型,表示独一无二的值。
不可以用new,可已传入描述性参数
这样可已来解决对象属性名可能冲突的问题。
// 使用Symbol值模拟私有方法
const fetch = Symbol('fetchData');
class DetailService extends Service {
// 避免覆盖框架提供的同名方法
async [fetch]({ apis = [] } = {}) {
......
}
}
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。
它也不是私有属性,有一个Object.getOwnPropertySymbols()
方法, 可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
const obj = {};
const foo = Symbol('foo');
obj[foo] = 'bar';
for (let i in obj) {
console.log(i); // 无输出
}
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [Symbol(foo)]
由于以 Symbol 值作为键名,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。
ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。
其中Symbol.iterator需要知道,这个跟遍历器有关,对象的Symbol.iterator属性指向该对象的默认遍历器方法。对象进行for…of 循环时,会调用Symbol.iterator方法返回该对象的默认遍历器。
2 iterator(遍历器)
js中有4种数据集合: Array、Object、Map、Set。数据结构又可以组合使用。所以需要统一的接口接口机制来处理不同的数据结构。
2.1 定义
iterator就是这样一种接口机制,任何数据结构只要部署了iterator接口,就能完成遍历操作既一次处理该数据结构的所有成员。
除了提供统一的访问接口,还能使得数据结构的成员能按某种次序排列。
同时也主要供 for…of(ES6新增的遍历命令)循环消费。
iterator的遍历过程如下:
1.创建一个指针对象,指向数据结构的起始位置。
2.调用指针对象的next方法,指针将指到第一个成员。并且返回信息,包含value和done两个属性的对象。
3.继续调用指针的next方法,指针指向数据结构的第二个成员。
依次调用,直到数据结构的结束位置。
2.2 默认接口
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator
属性,或者说,一个数据结构只要具有Symbol.iterator
属性,就可以认为是“可遍历的”(iterable)。Symbol.iterator
属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator
,它是一个表达式,返回Symbol
对象的iterator
属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内
2.3 原生具备 Iterator 接口的数据结构
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
如:
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
对于原生部署 Iterator 接口的数据结构,不用自己写遍历器生成函数,for...of
循环会自动遍历它们
2.4 for / forEach / for in/ for of 区别
参考:https://www.bookstack.cn/read/es6-3rd/spilt.7.docs-iterator.md
语雀内容