发表于: 2019-11-20 09:09:11
0 1282
js基础 - 续2
Iterables(可迭代对象 http://es6.ruanyifeng.com/#docs/iterator)
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
Iterable (可迭代对象)是数组的泛化。这个概念是说任何对象都可在 for..of
循环中使用。
数组本身就是可迭代的。但不仅仅是数组。字符串也可以迭代,很多其他内建对象也都可以迭代。
在核心 JavaScript 中,可迭代对象用途广泛。我们将会看到,很多内建的操作和方法都依赖于它。
Symbol.iterator
一个数据结构只要部署了Symbol.iterator属性就能使用 for...of遍历 与 ...运算符 操作
for of循环有很多优点,比如不像for...in一样只遍历键名(甚至包括原型链上的键),而且不像for each不能跳出循环。并且for...of为各种数据结构提供了一个统一的遍历方法。
es6中有三类结构生来就具有Iterator接口:数组、类数组对象、Map和Set结构。
对数组直接使用
let arr = [1,2,3,4];
console.log([...arr]); //(4) [1, 2, 3, 4]
如果你需要对对象进行迭代操作,就需要手动给你的对象部署iterator接口咯~
通过自己创建一个可迭代对象,我们就可以很容易的掌握它的概念。
例如,我们有一个对象,它并不是数组,但是看上去很适合使用 for..of
循环。
比如一个 range
对象,代表了一个数字区间
为了让 range
对象可迭代(也就让 for..of
可以运行)我们需要为对象添加一个名为 Symbol.iterator
的方法(一个特殊的内置标记)。
- 当
for..of
循环开始,它将会调用这个方法(如果没找到,就会报错)。 - 这个方法必须返回一个迭代器 —— 一个有
next
方法的对象。 - 当
for..of
循环希望取得下一个数值,它就调用这个对象的next()
方法。 next()
返回结果的格式必须是{done: Boolean, value: any}
,当done=true
时,表示迭代结束,否则value
必须是一个未被迭代的新值。
这是 range
的全部实现:
let range = {
from: 1,
to: 5
};
// 1. 使用 for..of 将会首先调用它:
range[Symbol.iterator] = function() {
// 2. ...它返回一个迭代器:
return {
current: this.from,
last: this.to,
// 3. next() 将在 for..of 的每一轮循环迭代中被调用
next() {
// 4. 它将会返回 {done:.., value :...} 格式的对象
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
};
// 现在它可以运行了!
for (let num of range) {
alert(num); // 1, 然后 2, 3, 4, 5
}
这段代码中有几点需要着重关注:
range
自身没有next()
方法。- 相反,是调用
range[Symbol.iterator]()
时将会被创建的另一个所谓的“迭代器”对象,将会处理迭代操作。
所以,迭代器对象和迭代的对象其实是分离的。
字符串可迭代
数组和字符串是应用最广泛的内建可迭代对象。
对于一个字符串,for..of
循环它的每个字符(对于UTF-16 的扩展字符也能正常工作):
for (let char of "test") {
alert( char ); // t,然后 e,然后 s,然后 t
}
显式调用迭代器
通常情况下,迭代器的内部函数对外部代码是隐藏的。for..of
循环可以工作,就是代码需要了解的所有内容了。
但是为了更深层的了解知识概念,我们来看看如何显式的创建迭代器。
我们将会采用与 for..of
一样的方法迭代字符串,但是是直接的调用。这段代码将会获取字符串的迭代器,然后“手动”调用它。
let str = "Hello";
// 和下面代码完成的功能一致
// for (let char of str) alert(char);
let iterator = str[Symbol.iterator]();
while (true) {
let result = iterator.next();
if (result.done) break;
alert(result.value); // 一个一个输出字符
}
评论