在 JavaScript 中,可迭代对象(Iterable)和迭代器(Iterator)是绝大部分前端开发者都应该掌握的知识点。它们可以帮助我们对数据集合进行基于迭代的操作,是 ES6 中新增的重要特性之一。
本文将重点介绍可迭代对象和迭代器的概念、语法、使用方法,并提供一些相关实例,以帮助读者深入理解它们的应用场景,提高代码的可读性和可维护性。
什么是可迭代对象?
在 JavaScript 中,可迭代对象是指可以被迭代的对象。一个对象如果拥有 Symbol.iterator 属性,则它就是一个可迭代对象,该属性必须是一个返回迭代器的函数。
Symbol.iterator 属性是 ES6 新增的内置符号,表示对象遵循了可迭代协议(Iterable Protocol)。该协议定义了一个可以迭代的对象必须具有的接口约束,这个接口包括一个 next 方法,用于返回迭代器的下一个值。next 方法返回一个对象,该对象包含两个属性:value 和 done。value 属性表示迭代器的当前值,done 属性表示迭代器是否已完成。
在实际代码实现中,可迭代对象通常用于数组、字符串、Map、Set 等数据类型。
什么是迭代器?
迭代器是一种对象,实现了可迭代协议。当一个迭代器对象被调用 next 方法时,它会返回一个包含 value 和 done 两个属性的对象,其中 value 表示下一个要迭代的值,done 表示迭代器是否已完成。
迭代器本身并不是可迭代对象,但它可以创建可迭代对象。创建一个可迭代对象需要用到 Symbol.iterator 属性,该属性是一个函数,返回一个实现了生成迭代器的 next 方法的对象。一个可迭代对象通过调用 Symbol.iterator 属性获取迭代器,并调用 next 方法来迭代它的值。
基础语法
Symbol.iterator
要创建一个可迭代对象,需要在对象上添加一个 Symbol.iterator 属性。ES6 引入了这个内置符号,用于定义一个可迭代对象。该属性是一个函数,用来生成迭代器,返回的是迭代器对象。
示例:
const iterableObj = { [Symbol.iterator]: function* () { yield 1; yield 2; yield 3; } };
for...of
for...of 语句用于遍历一些集合,包括数组、Set、Map、字符串等可迭代对象。
示例:
const iterable = [1, 2, 3]; for (const value of iterable) { console.log(value); } // output: 1 2 3
迭代器
要创建一个迭代器,定义一个函数,该函数使用一个 Generator,它返回一个包含 next 方法的对象。
示例:
-- -------------------- ---- ------- --------- ----- - --- - - -- ----- ------ - ----- ---- - - ----- -------- - ------ ----------------------------------- -- ------- - ----------------------------------- -- ------- - ----------------------------------- -- ------- -
Iterator 的实践
现在我们通过实现一个简单的可迭代对象和一个迭代器的例子来了解 Iterator 的使用。
示例:
-- -------------------- ---- ------- -- --------- ------- ----- ------- - - ------ -- ----- -------- ------ - -- - ----- --------- ------ - -- - ----- ------- ------ - --- ------------------- - --- ----- - -- ----- ----- - ----------- ----- ------ - ------------- ------ - ------ - -- ------ - ------- - ------ - ------ --------------- ----- ----- -- - ---- - ------ - ------ ---------- ----- ---- -- - - -- - -- -- ---- --- -- ---------- --- ------ ----- -- -------- - ------------------------ -
运行结果:
apple banana pear
在上面的代码中,我们定义了一个名为 factory 的对象。该对象包含了一个名为 items 的数组属性,它里面存储了一些水果的名称和价格信息。我们通过实现 Symbol.iterator 函数来使 factory 可被迭代。它返回一个对象,该对象包含了一个方法 next,用于返回可迭代对象下一个值的描述对象。在 next 方法中,通过检查 index 的值是否小于数组长度来表示迭代是否完成。
ES11 中Iterator 的新特性
在 ES11 中,迭代器新增了一些新的特性,包括异步迭代和生成器函数作为可异步迭代对象返回。
异步迭代
异步迭代与同步迭代类似,当没有更多的异步值可以返回时,done 属性为 true。
具体实现,需要在 Symbol.asyncIterator 属性中定义一个异步迭代器。对象中定义的 asyncIterator 符号不同于 Symbol.iterator。
示例:
-- -------------------- ---- ------- ----- --------- ---------------- - --- - - -- ----- -- - -- - ----- --- --------------- -- ------------------- ------- ----- ---- - - ------ -------- -- - ----- ------------- - ----------------- ----------------- ---------------------- ----------------- ---------------------- ----------------- ---------------------- ----------------- ---------------------- -----
输出:
{done: false, value: 0} {done: false, value: 1} {done: false, value: 2} {done: true, value: undefined}
在这个示例中,我们定义了一个生成器函数 asyncGenerator,该函数通过 yield 关键字来暂停函数执行,实现异步的下一个值。我们还定义了一个异步函数来迭代它,并使用 await 运算符来等待异步值转换。接下来,我们使用 next 函数来检查迭代器是否完成。
生成器函数作为可异步迭代对象返回
我们还可以使用生成器函数作为可异步迭代对象返回。在这种情况下,生成器函数中生成的值都必须是异步的。
示例:
-- -------------------- ---- ------- ----- --------- ---------------- - --- ---- ----- - -- ----- - -- -------- - ----- --- --------------- -- ------------------- ------- ----- ------ ----- ---------- - - ----- -------- ------ - --- ----- ------ ----- -- ----------------- - ------------------- - - -------
输出:
async value 0 async value 1 async value 2
在这个示例中,我们将生成器函数 asyncGenerator 作为可异步迭代对象返回,在 for await of 语句中使用。
总结
在本文中,我们详细介绍了可迭代对象和迭代器的基础语法和应用场景,包括定义可迭代对象和迭代器、for...of、生成器函数和异步迭代。我们在实践中实现了一个简单的可迭代对象和一个迭代器,以加强对它们的理解。
作为前端开发中的重要特性,借助于可迭代对象和迭代器,我们可以轻松处理集合操作,提高代码的可读性和可维护性。这使得我们可以更快更便捷的开发出高质量的个人和团队项目。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64af886848841e9894b97a66