iterator
经常被使用,例如在spread
运算符、for/of
-循环、解构等中。但它们是隐藏的。我想知道是否存在您会积极使用如何实现迭代器的知识的用例?
例如,使用迭代器对数组进行迭代过于复杂,如下所示,我不知道为什么有人会自己实现迭代器:
function arrayIterable(arr = []) {
let index = 0;
const len = arr.length;
const arrayIterator = {
next: () => {
let result;
if (index === len) {
return { value: arr[index], done: true };
}
result = { value: arr[index], done: false }
index++;
return result;
}
};
return arrayIterator;
}
const myArr = ['a','b','c','d'];
let iter = arrayIterator(myArr);
let result = iter.next();
while (!result.done) {
console.log(result.value);
result = iter.next();
}
如果您想在数据集上懒散地操作,这很方便。一个流、一个文件、一个数据库,您可以从一行/记录移动到另一行,并推进迭代器。没有必要把历史留在记忆中。
由于不必在内存中维护整个源,因此还可以处理无限数据源的情况。
迭代器最大的优势是在客户端。在预迭代器时代的代码中,通常会给您一个类似数组的对象来公开索引。然而,在现代代码中,可以为您提供迭代器,这意味着客户端使用相同的代码处理更一般的结果。请参阅此问题下的讨论以获取示例案例。
我不认为它是如何实现的知识会被用来实际迭代。与使用for of循环相比,这没有任何优势。
但假设您正在构建一个JavaScript库,例如MongoDB数据库的Node.js驱动程序。您希望使查询数据库和循环结果变得容易。你实现了可迭代的协议,然后人们就可以这样做:
const cursor = queryDatabase(<some query>)
for (let doc of cursor) {
// do something with doc
}
事实上,MongoDB驱动程序确实做到了这一点(除了它们实现了异步迭代器(。
EDIT:注意使用迭代器协议相对于从queryDatabase()
返回类似数组的对象的好处。特别是在MongoDB中,cursor
并不能保存所有的结果。它是一个句柄,通过调用cursor.next()
可以获得查询结果
正如您在问题中指出的,必须调用cursor.next()
的问题在于它相当笨重。然而,这是好的,因为并非所有的结果都需要从数据库中提取,数据库中可能有数千个。因此,迭代器协议是一种保持cursor.next()
优点的方法,而不必处理丑陋的语法。
您可以在MDN:上找到JavaScript中迭代器技术的全面介绍
请参阅MDN:迭代协议
它还包含应用领域、用法和示例。