简单理解迭代器模式

简介: 这几天研究了一下迭代器模式,期间有一段时间经常搞不太懂一些概念与概念之间的关系,今天来整理一下。

这几天研究了一下迭代器模式,期间有一段时间经常搞不太懂一些概念与概念之间的关系,今天来整理一下。

迭代的一些基本概念

  1. 循环是迭代机制的基础
  2. 迭代在一个有序集合上进行
  3. 按照顺序反复多次执行一段程序,通常会有明确的终止条件

我的理解:

实际上就是为了优化循环,各种数据结构的循环。而且各种数据结构循环起来可以千奇百怪,为了合理的统一,就有了迭代器模式。

关键词

  • 可迭代对象
  • 可迭代协议(Iterable接口)
  • 迭代器
  • 迭代器协议(Iterator接口)
  • 迭代器对象( IteratorResult

关系图

网络异常,图片无法展示
|

QA式学习

Q:什么是可迭代对象?

A:满足可迭代协议(实现Iterable接口)的对象。

Q:可迭代协议是啥?

A:就是Iterable接口。满足可迭代协议的对象应该满足以下条件:

  1. 能够创建实现了Iterator接口的对象(实际上就是迭代器)
  2. 且可以通过迭代器Iterator消费。

举个例子,数组,集合,映射等等都满足可迭代协议。他们都可以用for...of遍历。

Q:什么是消费?

A:可以理解为遍历。有一个相关的概念“耗尽”,可以理解为遍历结束了。

Q:怎么满足可迭代协议?

A:你的对象需要有一个键名为Symbol.iterator的属性,指向一个迭代器工厂函数。啥意思嘞?就是说

//jojo是一个可迭代对象(数组)
console.log(jojo[Symbol.iterator]); // ƒ values() { [native code] }

JavaScript

Copy

作为一个工厂函数,我们调用它的话就应该可以生成一个迭代器

console.log(jojo[Symbol.iterator]()); //Array Iterator {}

JavaScript

Copy

Q:什么是迭代器?

A:首先,迭代器是用于迭代与其关联的对象的一次性使用对象,迭代器满足迭代器协议(实现Iterator接口)。一次性是指其在完成一次遍历(消费)之后就会被“耗尽”,这个时候再想遍历只能通过重新生成一个迭代器。

Q:迭代器协议说了啥?

A:迭代器协议说,只要你实现了Iterator接口,你就是个迭代器辣!你至少需要有一个next()方法来返回一个迭代器对象IteratorResult。这个对象包含两个属性:donevalue。其中done为一个布尔值,当done不为真时表示还可以通过调用next()取得下一个值,当done为真时,就可以被称为“耗尽”了。当done不为真时,value对象表示可迭代对象的下一个值,而当done不为真时,value就自然为undefined了。

模拟for...of

在MDN上有这么一段话

The for...of statement creates a loop iterating over iterable objects, including: built-in String, Array, array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined iterables.

大意

for...of语句为可迭代对象创建循环迭代。这些可迭代对象包括内置的StringArray,和一些类数组对象(比如argumentsNodeList),TypedArrayMapSet和用户定义的可迭代对象。

也就是说实际上使用for...of来遍历正是迭代器模式的一个应用。通过模拟一个数组的for...of遍历来更好地理解一下迭代器。

当我们普普通通for..of的时候发生了甚么事呢?

let arr = [1,2,3,4,5];
for(let item of arr)
    console.log(item);

JavaScript

Copy

实际上上面的代码可以等价于下面的代码。

let arr = [1,2,3,4,5];
let it = arr[Symbol.iterator]();//it->迭代器,通过调用arr[Symbol.iterator]()来生成
let item = it.next();//item->迭代器对象,包含着done和value两个属性
while(!item.done) {//当迭代器没有耗尽时
    console.log(item.value);//可以通过item.value来访问当前迭代到的值
    item = it.next();//继续迭代
}

JavaScript

Copy

自定义迭代器

刚刚提到了,for...of同样可以用于遍历用户定义的可迭代对象。一般的可迭代对象是不可以用for...of来遍历的,但是我们可以通过改造我们的对象,使其满足可迭代协议来使用for...of

let colors = {
    blue : "蓝色",
    green : "绿色",
    yellow : "黄色"
};
for(let color of colors)
    console.log(color);

JavaScript

Copy

网络异常,图片无法展示
|
尖尖达咩

现在我们让color对象满足Iterable接口

colors[Symbol.iterator] = function() {
    let keys = Object.keys(colors);
    let index = 0;
    return {
        next : function() {
            if (index < keys.length) {
                return {
                    value : colors[keys[index++]],
                    done : false
                }
            }
            return { done : true }
        }
    }
}

JavaScript

Copy

然后再次for...of循环,可以发现没有报错,并且正常循环输出了。

网络异常,图片无法展示
|

目录
相关文章
|
3月前
|
设计模式 安全 Java
Java设计模式-迭代器模式(21)
Java设计模式-迭代器模式(21)
|
7月前
|
设计模式 Java 数据挖掘
聊聊Java设计模式-迭代器模式
迭代器(Iterator)模式,也叫做游标(Cursor)模式。我们知道,在Java 容器中,为了提高容器遍历的方便性,我们利用迭代器把遍历逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合容器的内部结构。
64 0
聊聊Java设计模式-迭代器模式
|
7月前
|
设计模式 uml C++
行为型 迭代器模式
行为型 迭代器模式
45 0
|
设计模式 存储 算法
设计模式~迭代器模式(Iterator)-20
迭代器模式(Iterator Pattern)是Java和.Net编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。迭代器模式已经被淘汰,java中已经把迭代器运用到各个聚集类(collection)中了,使用java自带的迭代器就已经满足我们的需求了 目录 迭代器模式(Iterator) (1)优点 (2)缺点 (3)使用场景 (4)注意事项 (5)应用实例: 代码
60 0
|
设计模式 存储 Java
迭代器模式
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种顺序访问聚合对象中每个元素的方法,而不暴露其内部实现。
104 1
|
容器
关于迭代器模式我所知道的
关于迭代器模式我所知道的
57 0
|
设计模式 存储 容器
我学会了,迭代器模式
迭代器模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
104 0
我学会了,迭代器模式
|
Java 容器
迭代器模式
迭代器模式
115 0
|
Java uml 容器
被用到炉火纯清的迭代器模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
118 0
被用到炉火纯清的迭代器模式
|
设计模式 存储 Java
迭代器模式:理解与实践
上面的这段代码通过循环逐一将arr的下标加1,从而实现了遍历数组的功能。 但是通过循环实现遍历的话依赖于集合对象内部,因此就有了一种能顺序访问集合对象中各个元素,又无需依赖对象内部表示的设计模式--迭代器模式。