Appearance
08. [...10]
试修改原型,实现以下效果:
js
console.log( [...10] )
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
2
2
本题其实就是要在 Number
原型上实现一个扩展运算符,这样就能够实现 [...num]
,其中 num
为整数。
【原理分析】扩展运算符执行的原理是:
- 首先看是否有实现可迭代协议规定的方法,也就是
[Symbol.iterator]
这个函数(方法)是否存在,若存在,则可以进行扩展; - 其次,ES2019 对于对象也实现了扩展运算符,但是一般对象并没有可迭代方法,这是ES 规范特殊的扩展运算符的实现。
也就是说,我们要在 Number
原型上定义 [Symbol.iterator]
可迭代方法。
【代码实现】
js
Number.prototype[Symbol.iterator] = function () {
let index = 0
const arr = Array.from({ length: +this }, (_, i) => i + 1)
return {
next: () => {
if (index < arr.length) {
return {
value: arr[index++],
done: false
}
}
return {
value: undefined,
done: true
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TIP
不熟悉迭代器的朋友可以前往 MDN 学习:迭代器与生成器
事实上,实现了整数的可迭代性后,整数也具有了可迭代类型的其他特性,比如 let/const ... of ...
js
for (const n of 5) {
console.log(n)
}
// 打印 1、2、3、4、5
1
2
3
4
2
3
4
一般我们会用生成器和 yield
替代迭代器(实际上生成器是一种特殊的迭代器),简化代码。上述例子的另一个方案是:
js
Number.prototype[Symbol.iterator] = function* () {
yield* Array.from({ length: +this }, (_, i) => ++i)
}
console.log([...10])
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
2
3
4
5
6
2
3
4
5
6