迭代器是一个对象,它使我们可以一次访问一组对象。
以下内置类型默认情况下是可迭代的-
- String
- Array
- Map
- Set
如果对象实现了键为[Symbol.iterator]并返回迭代器的函数,则该对象被视为可迭代。for ... of循环可用于迭代集合。
let marks = [10,20,30]
//check iterable using for..of
for(let m of marks){
console.log(m);
}
下面的示例声明一个数组,标记并检索一个迭代器对象。的[Symbol.iterator]()可以被用于检索一个迭代器对象。迭代器的next()方法返回具有'value'和'done'属性的对象。'done'是布尔值,在读取集合中的所有项目后返回true。
<script> let marks = [10,20,30] let iter = marks[Symbol.iterator](); console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) </script>
输出:
{value: 10, done: false} {value: 20, done: false} {value: 30, done: false} {value: undefined, done: true}
自定义迭代
JavaScript中的某些类型是可迭代的(例如,数组,映射等),而其他类型则不是。默认情况下不可迭代的JavaScript类型可以使用可迭代协议进行迭代。
下面的示例定义一个名为CustomerList的类,该类将多个客户对象存储为一个数组。每个客户对象都有firstName和lastName属性。
为了使此类可迭代,该类必须实现[Symbol.iterator]()函数。该函数返回一个迭代器对象。迭代器对象具有下一个返回对象{value:'customer',done:true / false}的函数。
<script> //user defined iterable class CustomerList { constructor(customers){ //adding customer objects to an array this.customers = [].concat(customers) } //implement iterator function [Symbol.iterator](){ let count=0; let customers = this.customers return { next:function(){ //retrieving a customer object from the array let customerVal = customers[count]; count+=1; if(count<=customers.length){ return { value:customerVal, done:false } } //return true if all customer objects are iterated return {done:true} } } } } //create customer objects let c1={ firstName:'Sachin', lastName:'Tendulkar' } let c2={ firstName:'Rahul', lastName:'Dravid' } //define a customer array and initialize it let customers=[c1,c2] //pass customers to the class' constructor let customersObj = new CustomerList(customers); //iterating using for..of for(let c of customersObj){ console.log(c) } //iterating using the next() method let iter = customersObj[Symbol.iterator](); console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) </script>
输出:
{firstName: "Sachin", lastName: "Tendulkar"} {firstName: "Rahul", lastName: "Dravid"} { done: false value: { firstName: "Sachin", lastName: "Tendulkar" } } { done: false value: { firstName: "Rahul", lastName: "Dravid" } } {done: true}
Generator
在ES6之前,JavaScript中的函数遵循运行完成模型。ES6引入了称为Generator的功能,该功能可以在中途停止,然后从停止的地方继续。
生成器在函数名称前添加星号*字符,并包含一个或多个yield语句。yield关键字返回一个迭代器对象。
语法:
function * generator_name() { yield value1 ... yield valueN }
该示例使用三个yield语句定义了生成器函数getMarks。与普通函数不同,生成器函数getMarks()在被调用时不会执行该函数,而是返回一个迭代器对象,该对象可帮助您在生成器函数内执行代码。第一次调用markIter.next()时,将运行操作,并且yield语句会暂停生成器的执行。随后对markIter.next()的调用将恢复生成器函数,直到下一个yield表达式为止。
<script> //define generator function function * getMarks(){ console.log("Step 1") yield 10 console.log("Step 2") yield 20 console.log("Step 3") yield 30 console.log("End of function") } //return an iterator object let markIter = getMarks() //invoke statements until first yield console.log(markIter.next()) //resume execution after the last yield until second yield expression console.log(markIter.next()) //resume execution after last yield until third yield expression console.log(markIter.next()) console.log(markIter.next()) // iteration is completed;no value is returned </script>
输出:
Step 1 {value: 10, done: false} Step 2 {value: 20, done: false} Step 3 {value: 30, done: false} End of function {value: undefined, done: true}