es6的迭代器--Iterator

一、什么是for-of循环

对于如下一个数组,遍历其中的值方法有哪些?

var arr = ['a', 'b', 'c'];

首先想到的可能就是如下这种,这也是js最原始的遍历方法,和java的语法一样。

 var arr = ['a', 'b', 'c'];
 for (var i=0;i<arr.length;i++) {
     console.log(arr[i]);
 }

如果你了解ES5,还可以写出for-in的方法。

var arr = ['a', 'b', 'c']; 
for(var i in arr){
   console.log(arr[i]);
}

今天为大家再介绍一种for-of的遍历方法

var arr = ['a', 'b', 'c']; 
for(var ch of arr){
    console.log(ch);
}

在这个例子中,大家注意到使用for-of时,ch不是数组的索引值,所示其中的value值。

那有了for-in,为什么还要设计for-of呢,或者说for-of有什么独特的地方。继续实例:

let arr = "abc";
for( var char of arr){
    console.log(char);
}

此时,可以将a,b,c输出,但是for-in是无能为力的。其中for-of不仅能对数组和字符串进行遍历。还可以适用以下的集合:

Map

Set

NodeList

其中Map,Set是ES6新增的特性,现在不了解也没关系,我们稍后单独讲。NodeList是DOM对象集合,有兴趣的可能查阅资料了解,不在这里展开讨论。

二、迭代器(Iterator)实现原理

再看一个普通的字面量对象例子:

var obj={0:"rrr",1:"444"};
   for(var value of obj){
     console.log(value);
   }

运行后发现报错,表明这个字面量对象是不可遍历的。那能否像Array,String等对象一样支持for-of遍历呢?答案是可以的,Array,String等对象之所以可遍历,是因为在他们的原型上,实现了迭代器(Iterator)的接口。

那如何实现迭代器(Iterator)接口呢,只需要在这个对象中实现[Symbol.iterator]属性方法,[Symbol.iterator]这个属性名ka看起来怪怪的,Symbol是ES6表示唯一性的标识符,标准委员会是为了避免命名的冲突,所以才这样命名,大家作为一个唯一的字符串理解即可,不去深究。下面我们来实现[Symbol.iterator]属性。如下:

var obj={
    0:"rrr",
    1:"444",
    //实现[Symbol.iterator]属性方法
    [Symbol.iterator]:function(){
        const self = this;
        let index=0;
        return {
          next:function(){//实现next
            if(index<2){
              return {//遍历中
                value:self[index++],
                done: false//表示遍历没有结束,done设置为fasle
              }
            }else{
              return{//遍历结束
                value:undefined,//结束后,返回undefined
                done: true//done设置为true,表示遍历结束
              }
            }
          }
        }
     } 
    };
   for(var value of obj){
     console.log(value);//"rrr","444"
   }

此时正确的遍历了obj,打印了obj的属性的值。再来看下[Symbol.iterator]属性函数体,返回了next方法,next方法中遍历了此obj的属性对象,并返回字面量对象{value:xxx,done:xxx}这种结构对象,在遍历过程中,value返回对应属性值,且done设置为false;当遍历结束后,value返回undefined,且done设置为true。

var it = obj[Symbol.iterator]();
console.log(it.next());//{value: "rrr", done: false}
console.log(it.next());//{value: "444", done: false}
console.log(it.next());//{value: undefined, done: true}

这就是for-of的原理,每次遍历都会调用该对象的[Symbol.iterator]属性的next方法,当返回{value: undefined, done: true}后,表示遍历结束。

所以讲到这,各位道友是否就明白了,任何对象要变成可遍历的对象,只需要实现[Symbol.iterator]属性方法,定义其中的next方法即可。

三、break,continue

学过java的道友们,对break,continue应该再熟悉不过了,意义我就不再阐述。for-of对于for-in的优点就是它能支持这些语句。我们接着往下看。

let arr = "abc";
for( var char of arr){
      console.log(char);//"a"
      break;
}

仅输出了“a”就跳出了循环。有兴趣的道友可以再实验下continue,看看效果。

好了,我们将上面obj的实例再修改下,使其支持这些语句

var obj={
    0:"rrr",
    1:"444",
    //实现[Symbol.iterator]属性方法
    [Symbol.iterator]:function(){
        const self = this;
        let index=0;
        return {
          next:function(){//实现next
            if(index<2){
              return {//遍历中
                value:self[index++],
                done: false//表示遍历没有结束,done设置为fasle
              }
            }else{
              return{//遍历结束
                value:undefined,//结束后,返回undefined
                done: true//done设置为true,表示遍历结束
              }
            }
          },
         return:function() {//增加return,支持continue,break
          return { done: true };
        }
        }
     } 
    };
   for(var value of obj){
     console.log(value);//"rrr"
     break ;
   }

此时仅输出了"rrr"就跳出了循环,在执行break时,内部调用了return的方法,返回了{done:false},continue也是如此。

四、总结

主要学些了for-of循环,并通过这个循环讲述了迭代器(Iterator)的实现原理。for-of的用处还是很强大的,可以和我们下一章节要介绍的Generator对象很好的结合。

ES6迭代器Iterator)是一种新的遍历机制,它有两个核心特点。首先,迭代器是一个接口,通过Symbol.iterator方法来创建迭代器,并通过迭代器的next()方法来获取数据。其次,迭代器是用于遍历数据结构的指针,类似于数据库的游标。例如,我们可以使用迭代器来遍历数组。比如,对于数组\[20,30,50,20,50\],我们可以通过arr\[Symbol.iterator\]()来创建一个迭代器,然后使用迭代器的next()方法来逐个获取数组中的元素。\[1\] 除了数组,具备Iterator接口的数据结构都可以进行解构赋值和扩展运算符(...运算符)操作。例如,字符串也具备Iterator接口,我们可以使用扩展运算符将字符串转换为字符数组。比如,对于字符串'hello',我们可以使用\[...str\]来将其转换为字符数组\['h', 'e', 'l', 'l', 'o'\]。这是因为字符串是具备Iterator接口的数据结构,我们可以自定义迭代器来遍历字符串中的字符。\[2\] 除了数组和字符串,还有其他可迭代的数据结构,比如类型数组(TypedArray)。我们可以使用for...of循环来遍历这些可迭代的数据结构。例如,对于数组\["zero", "one", "two"\],我们可以使用for...of循环来逐个输出数组中的元素。\[3\] #### 引用[.reference_title] - *1* [ES6 迭代器Iterator](https://blog.csdn.net/weixin_49342009/article/details/122665011)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [es6 迭代器iterator](https://blog.csdn.net/weixin_43443341/article/details/121417247)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ES6迭代器 Iterator 详细介绍](https://blog.csdn.net/weixin_43856422/article/details/128290261)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值