6.1.5 ECMAScript®2020 标准文档 - Symbol类型

Symbol 符号类型

Symbol 类型是所有非字符串值的集合,可以被用来作为对象属性的 key

每个符号类型的值都是唯一且不可变的。

且每个 Symbol 类型的值都会有一个与之相关联的的内置属性值,叫 [[Description]]

该值可以是 undefined 或者一个字符串。

知名的 Symbol

@@hasInstance : Symbol.hasInstance

对象实例检测,在我们使用 instanceof 的时候,实际内部是调用了 Symbol.hasInstance

下面我们可以来看个实例,通过重写 Symbol.hasInstance 来改变 instanceof 的结果。

1
2
3
4
5
6
7
8
class Person {
static [Symbol.hasInstance]() {
return 0
}
}

const p1 = new Person()
console.log(p1 instanceof Person)

+RESULTS:

false
undefined

我们尝试修改 return 0 的返回值,会发现所有的控制得到的结果为 false 相反则为 true

很显然 p1Person 类的实例,但我们却可以改变这种默认行为,从某种程度上来说是很不安全的,建议

最好不要修改 instanceof 的默认行为。

@@asyncIterator : Symbol.asyncIterator

异步迭代器,在使用 for...of 遍历一个对象的时候,实际上是调用了该对象内部的 Symbol.iterator 函数,来看下面的实例印证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Person {

constructor() {
this.name = 'simon'
this.age = '32'
this.nums = [1, 2, 3]
}

[Symbol.iterator]() {
let i = 0
return {
next: () => {
const len = this.nums.length
if (i >= len) {
return { value: undefined, done: true }
} else {
return { value: this.nums[i++], done: false }
}
}
}
}
}


const p1 = new Person()

for (const value of p1) {
console.log('value: ' + value)
}

+RESULTS:

value: 1
value: 2
value: 3
undefined

Person 中我们通过 Symbol.iterator 重写了该类的迭代器,从而返回了我们设定的结果,如上。

而这里的返回结果是属于同步的,且 Symbol.iterator 里面只能返回同步结果。

如果我们想要返回一个异步结果该怎么处理,在 Symbol.iterator 中这么做???

try Symbol.asyncIterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Person {
constructor() {
this.vals = [1, 2, 3]
}

[Symbol.asyncIterator]() {
let i = 0
return {
next: () => {
const value = this.vals[i]
const done = !(i++ in this.vals)
return new Promise(resolve => setTimeout(() => resolve({
value, done
}), 1000))
}
}
}
}

const travel = async () => {
const p1 = new Person()
// 启动 tick
const t = tick()

for await (const value of p1) {
console.log('value: ' + value)
}

// 结束 tick
clearInterval(t)
}

// 1. 这里会将会有以下输出:
// 第一个 undefined 是 emacs org-mode 默认输出结果,
// 然后这却很好的为我们提供了异步输出的证据,非异步情况下这个 undefined 都是最后输出的,
// 参考上面代码的结果
// : undefined
// : value: 1
// : value: 2
// : value: 3
const t1 = travel()

// 为了证明是异步结果,我们可以来试着增加一个 `tick` 功能
let i = 1
function tick() {
return setInterval(() => console.log('tick ' + i * 500), 500)
}

+RESULTS:

undefined
tick 500
value: 1
tick 500
tick 500
value: 2
tick 500
tick 500
value: 3
tick 500
tick 500

总结:

  1. 迭代器的特点,必须要有个 next() 函数,启动迭代器往下执行;

  2. 异步迭代器特征,在 next() 函数内必须返回一个 Promise

0%