Es6的迭代器深入理解

Es6的迭代器深入理解

今天学习了Es6中的迭代器的知识,在这里做一个总结。

一、 概念理解:

迭代器:就是可以将一个有限并且有序的数据类型,进行有序输出的函数。
可迭代对象:就是具有可迭代接口的实例化对象。
迭代器工厂函数:例如Symbol.iterator就是迭代器工厂函数。

二、可迭代的数据类型
<script>
 let arr = [1, 2, 3, 4, 5, 6];
 let str = 'woshidongli';
 let obj = { a: 3, b: 5 };
for(let x of arr){
     console.log(x);
  }
for(let x of str){
      console.log(x);
  }
 for(let x of obj){
      console.log(x);
 }  //迭代器_1.html:26 Uncaught TypeError: obj is not iterable
</script>

由此可见数组有可以进行迭代,字符串也可以,但是Object不可以迭代。
原因:因为迭代对象必须是有限的,并且有次序的,但是当我们查看这几种数据类型输出的时候。
在这里插入图片描述
这里数组类型有序号,但是对象类型序号。
但这并不是根本的原因:根本的原因是:是否有可迭代接口(Symbol.iterator)当我们使用Object.getPrototypeOf()来访问实例对象原型时。
数组和字符串中在这里插入图片描述
对象中
在这里插入图片描述
对象中并没有Symbol.iterator,所以可以知道不可以迭代。

拓展
<script>
 let str = 'abcd';
    let arr = ['a','b','c','d'];
    let map = new Map().set("a",1).set('b',2);
    let set = new Set().add("a").add('b').add('c');
    let nodelist = document.querySelectorAll("div");
    console.log(str[Symbol.iterator]);
    console.log(arr[Symbol.iterator]);
    console.log(map[Symbol.iterator]);
    console.log(set[Symbol.iterator]);
    console.log(nodelist[Symbol.iterator]); 
</script>

由此可以知道,Map,Set,NodeList,Array,String,等数据类型都是可以迭代的。

三、迭代器内部实现

迭代实现原理就是,当可迭代实例对象进行循环遍历的时候,就会调用接口执行其中的函数。
下面我们手写数组的迭代器。

<script>
  let arr = [1,2,3,4,5,6,7];
    arr[Symbol.iterator]=function(){
      let index = 0;
      return {
        next(){
          if (index<arr.length){
            return{
              value:arr[index++],
              done:false
            }
          }
          else{
            return {
              value:undefined,
              done:true
            }
          }
        }
      }
    }
    let itertor = arr[Symbol.iterator]();
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
    console.log(itertor.next());
</script>

最终结果
在这里插入图片描述
Object对象没有迭代对象
我们下面手写对象的迭代器

<script>
  let obj = {
      a:1,
      b:2,
      c:3,
      d:4,
      [Symbol.iterator](){
        let index = 0 ;
        let map = new Map([["a",1],["b",2],["c",3],["d",4]]);
        return {
          next(){
          if(index<map.size){
            return {
               value:[...map][index++],
               done:false,
            }
          }
          else{
            return{
              value:undefined,
              done:true
            }
          }
        }
        }
      }
    }
    for (const x of obj){
      console.log(x);
    }
</script>

最终结果:
在这里插入图片描述
解析:这里我们采用了Map作为中间转化,因为Map是可迭代的数据类型。我们也可以使用Object.keys() Object.values() Object.entries()这三个来对对象进行迭代。
还有一点比较重要:当一个实例化对象可以进行迭代,他的[Symbol.iterator]也可以进行迭代,也就是说实例化对象的[Symbol.iterator]也存在iterator接口。

四、迭代器协议
<script>
  let arr = ['arr','bat'];
    let text_1 = arr[Symbol.iterator]();
    let text_2 = arr[Symbol.iterator]();
    console.log(text_1.next());
    console.log(text_2.next());
    console.log(text_1.next());
    console.log(text_2.next());
</script>
解析:当声明不同的迭代器的时候,这几个迭代器之间不互相干扰。
<script>
let arr = [1,2,4,5,6];
    let iterator = arr[Symbol.iterator]();
    console.log(iterator.next());
    arr.splice(1,0,3);
    console.log(iterator.next());

//{value: 1, done: false}
//{value: 3, done: false}
</script>

解析:迭代器使用的是游标记录迭代过程,当迭代过程中,实例化对象改变的时候,迭代器也会发生改变。

五、提前终止迭代器

我们在使用迭代器进行迭代的时候,可以在满足某一个条件的时候,就会提前终止迭代器。起始在[Symbol.iterator]也存在一个函数,return()函数,就是满足终止条件的时候,执行return()函数。
例子

<script>
 let arr = [1,2,3,4,5,6];
    let iterator = arr[Symbol.iterator]();
    iterator.return = function(){
      console.log("结束了");
      return {
        value:undefined,
        done:true
      }
    }
    for (const x of iterator){
      console.log(x);
      break;
    }
</script>

在这里插入图片描述

这里设置一个return函数,当执行结束的时候,就自动执行return中的。
但是数组有一个特点:不可关闭的,就是当数组break退出的时候,下一次,还是会继续在原来的游标位置开始迭代。

<script>
let arr = [1,2,3,4,5,6];
    let iterator = arr[Symbol.iterator]();
    iterator.return = function(){
      console.log("结束了");
      return {
        value:undefined,
        done:true
      }
    }
    for (const x of iterator){
      console.log(x);
      break;
    }
    for (const x of iterator){
      console.log(x);
    }
</script>

在这里插入图片描述
还有一点比较容易混淆:【Symbol.iterator】和【Symbol.iterator】(),
【Symbol.iterator】是工厂函数,【Symbol.iterator】()是迭代器,【Symbol.iterator】下面没有iterator接口,而【Symbol.iterator】()中有iterator接口,所有【Symbol.iterator】()可以进行迭代。
这些就是我对于ES6中的迭代器的理解,如果存在任何错误,请指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值