我是靠谱客的博主 壮观小熊猫,最近开发中收集的这篇文章主要介绍Iterator遍历器的使用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Iterator遍历器的作用

JS语言中包含众多具有“集合”性质的数据结构——比如数组、对象、Set以及Map等,很多时候用户会将其进行组合使用,比如数组里边嵌套对象,或是数组里边嵌套Map等,由此数据结构变得复杂起来。数据结构复杂化所导致的一个问题便是对其访问的难度会随之提升。对于具有“集合”性质并且存在多种不同数据结构嵌套的复杂结构,对其结构的遍历访问往往要求对数据结构进行逐层拆解,从而获得目标数据,这是一个复杂的过程,且复杂程度会随着结构复杂度而成倍提升。
为了便于进行访问,开发者在设计数据结构的同时也会开发相应的访问接口,通过对接口函数的直接调用从而“简化”对数据结构的访问过程(尽管从外部看来是简单明了的)。
Iterator遍历器的作用正是提供这样一个工具,其可以辅助开发人员,针对某个特定的(即由开发人员自己设计的)、具有“集合”性质的数据结构,建立一个个性化的遍历方案(或访问接口)。

Iterator遍历器的核心:next()方法

next()方法是实现Iterator遍历器的关键。
(1)从外部看,Iterator遍历器的实例对象只要调用next()方法,便能实现对数据结构的遍历访问。
(2)从内部看,该方法控制着返回的数据以及遍历是否结束的标识。

例程如下:

 var temp = creatIterator(['a','b','c']);
 console.log(temp.next());
 console.log(temp.next());
 console.log(temp.next());
 console.log(temp.next());

function creatIterator(arr) {
    //由于要进行全局访问,长期保存变量值,因此此处用var
    //而不用let,var所具有的变量提升特性在这里是必要的
    var nextIndex = 0;

    return {
        next:function() {
            return nextIndex < arr.length?
            //如果索引变量小于当前传入数组的长度,则将对应的有效数据传出,并将遍历的状态标识done置为false
            {value:arr[nextIndex++],done:false}:
            //如果索引变量大于当前传入数组的长度,则传出无效undefined,并将遍历的状态标识done置为true
            {value:undefined,done:true};
        }
    };
}

上述例程定义了一个函数,该函数可返回一个对象,通过该对象下的next()方法可实现对数组元素的遍历访问。
**注意:**该next()方法之所以具有移动、遍历的功能特性,完全取决于该方法中所定义的索引变量nextIndex是var属性(如果定义为let型变量,就没有这种效果了)。var所具有的变量提升特性可使得该变量在全局下有效。累加的结果会被长期记录,而不限于函数creatIterator()的作用块。
接下来说明如何部署一个具有默认Iterator接口的对象。

类部署Iterator接口

为类对象部署Iterator接口通常会为其声明Symbol.iterator属性(ES6规定)。一个数据结构若具有Symbol.iterator属性,在程序执行过程中即认为该数据结构具有“可遍历”的性质。

Symbol关键字说明
此处对Symbol关键字进行说明,若您已经对此有所掌握,可以直接跳过此节。
Symbol可作为一个数据类型,该数据类型具有唯一性(类似于产品出厂时带有唯一的出厂编号)

let type = Symbol();
console.log(type);

执行结果:
在这里插入图片描述
此处调用Symbol()函数可返回一个Symbol类型的值(不是对象),该值的类型是唯一的,具体看下边:

    let type1 = Symbol();
    let type2 = Symbol();
   
    console.log(type1);
    console.log(type2);
   
    if(type1===type2){
        console.log(true);
    }
    else{
        console.log(false)
    }

执行结果:
在这里插入图片描述
由上例可见,即使调用Symbol()函数,创建Symbol值的过程完全相同,所产生的结果依然是不同的(类型不同)
可以通过向Symbol()函数传递参数以为该Symbol类型添加描述(类似于代码注释或是附加说明),但对值类型的唯一性没有任何影响。

    let type1 = Symbol('saber');
    let type2 = Symbol('saber');

    console.log(type1);
    console.log(type2);

    if(type1===type2){
        console.log(true);
    }
    else{
        console.log(false)
    }

执行结果:
在这里插入图片描述
Symbol值使用场景的一个重要特点在于,该场景下并不关心目标的具体值是多少,只要目标是唯一的,可以与其它目标彼此区分的就可以。对Symbol值一种常见的使用方法是,将其作为对象的属性名,由于其具有的唯一性以防止对象的属性被轻易改写或覆盖。写法如下:

    let type = Symbol();
    
    //第一种写法
    let obj1 = {};
    obj1[type] = 'Hello';

    //第二种写法
    let obj2 = {
        [type]:'world'
    }

    console.log(obj1[type]);
    console.log(obj2[type]);

执行结果如下:
在这里插入图片描述
上述例子中,创建了两个对象obj1和obj2,并且分别为两个对象各添加了一个Symbol类型的属性,属性值分别为‘hello’和‘world’。
具有Symbol性质的对象属性在这里的写法可能会让一些人感到怪异,因为此处使用“[Symbol值]”直接作为属性名,而不是常规的用户自定义属性标识,这个习惯就好,因为接下来还会用“[Symbol值]”直接作为类对象的方法名(淦!!!)

为类对象部署Iterator遍历器接口
相比于数组、Set以及Map等线性数据结构(这些结构内部构成都是默认有序的)而言,用户自定义对象往往是非线性的(内部数据无严格的次序关系),因此对类对象部署遍历器的一个重要环节便在于——明确如何遍历这个对象。
为类对象部署Iterator遍历器接口的要点如下:
(1)该类对象必须包含Symbol.Iterator()方法,以声明该类对象是可以被遍历的;
(2)Symbol.Iterator()方法当中,必须返回一个包含next()方法的对象,以明确对类对象的遍历方式。包含Next()方法的对象和类对象自身可以是同一个,也可以不同。
示例代码如下:

class RangeIterator {
    constructor(start,stop) {
        this.value = start;
        this.stop = stop;
    }

    [Symbol.iterator] () {return this;}

    next() {
        var value = this.value;
        if(value < this.stop) {
            this.value ++ ;
            return {
                done:false,
                value:value
            };
        }

        return {
            done:true,
            value:undefined
        };
    }
}

function range(start,stop) {
    return new RangeIterator(start,stop);
}

for(var value of range(0,3)){
           console.log(value)
       }

上述代码定义了一个类RangeIterator,在该类中定义了名为next的方法,以指定对该类的遍历方式;其次包含了名为[Symbol.Iterator]的方法,在该方法中直接返回类自身(该类本身就包含next方法)由此满足要点2。
经过range()函数对该类进行实例化后,使用for…of语句进行遍历,执行结果如下:
在这里插入图片描述
此处注意一下,这里的value变量是var类型,所以其作用域是全局的,而不限于RangeIterator类的范围内。也正是如此,通过每次调用next()函数进行遍历的每一步才可被长期保存下来。

以上便是本人对Iterator遍历器使用的认知,如有不当之处,欢迎留言指正。

最后

以上就是壮观小熊猫为你收集整理的Iterator遍历器的使用的全部内容,希望文章能够帮你解决Iterator遍历器的使用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部