资讯专栏INFORMATION COLUMN

迭代器和生成器

MorePainMoreGain / 1777人阅读

摘要:迭代器和生成器一迭代器迭代器是带有特殊接口的对象返回一个方法,该方法中同时又和属性当再没有值可以迭代时,为,为,否则为当前值,为根据上面的描述实现一个迭代器,如下二生成器生成器是返回迭代器的函数,如下生成器有几点要注意的当执行流遇到语句时,

迭代器和生成器 一.迭代器

1.迭代器是带有特殊接口的对象,返回一个next方法,该方法中同时又valuedone属性,当再没有值可以迭代时,valueundefineddonetrue,否则value为当前值,donefalse

2.根据上面的描述实现一个迭代器,如下:

let iterator = {
    i: 0,
    items: [2, 4, 6],
    next() {
        let value, done;
        done = (this.i === this.items.length);
        value = done ? undefined : this.items[this.i++];
        return {
            value: value,
            done: done
        }
    }
};
console.log(iterator.next());  //{value: 2, done: false}
console.log(iterator.next());  //{value: 4, done: false}
console.log(iterator.next());  //{value: 6, done: false}
console.log(iterator.next());  //{value: undefined, done: true}
二.生成器

1.生成器是返回迭代器的函数,如下:

function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}
let iterator = createIterator();
console.log(iterator.next());  //{value: 1, done: false}
console.log(iterator.next());  //{value: 2, done: false}
console.log(iterator.next());  //{value: 3, done: false}
console.log(iterator.next());  //{value: undefined, done: true}

2.生成器有几点要注意的:

当执行流遇到yield语句时,该生成器就停止运转了,直到迭代器再次调用next

可以再for循环中使用yield

yield只能用在生成器的内部,即使是生成器内部的函数也不行,即:yield无法跨越函数边界

无法使用箭头函数创建生成器

生成器可以存在于对象的属性中

三.for-of循环

1.可迭代类型:指那些包含Symbol.iterator属性的对象,该属性定义了返回迭代器的函数(如:数组,set,map等)

2.for-of循环可以循环可迭代类型,for-of循环会在可迭代类型每次执行后调用next()并将结果存储在变量中,循环会持续进行,直到结果对象的done属性为true

3.for-of循环会调用数组的Symbol.iterator属性来获取迭代器(该方法由幕后的js引擎调用),并将调用iterator.next(),并将该结果对象的value属性的值赋给num,直到done为true,循环会退出,num不会被赋给undefined,代码如下:

let values = [1, 2, 3];
for (let item of values) {
    console.log(item);   //1 2 3
}

4.对于非可迭代对象,如nullundefined,使用for-of循环会抛出错误

5.可以在for-of循环中使用解构

let map = new Map();
map.set("name", "sxt");
map.set("age", 2);
for(let [key, value] of map) {
    console.log(key + " = " + value);
}
//输出:
//name = sxt
//age = 2

6.for-of循环可以用于循环NodeList

四.Symbol.iterator

1.可以用Symbol.iterator属性来访问对象默认的迭代器,如:

let arr = [6, 7, 8];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next());  //{value: 6, done: false}
console.log(iterator.next());  //{value: 7, done: false}
console.log(iterator.next());  //{value: 8, done: false}
console.log(iterator.next());  //{value: undefined, done: true}

2.判断一个对象是否可以迭代,可以通过判断Symbol.iterator属性是否是一个函数来实现,如:

function isIterator(obj) {
    return typeof obj[Symbol.iterator] === "function";
}

let arr = [1, 3, 4];
let num = 1;
console.log(isIterator(arr)); //true
console.log(isIterator(num)); //false

3.创建可迭代类型: 我们自己定义的对象默认是不可迭代类型,但是我们可以通过设置Symbol.iterator属性来使这个对象可以迭代。因为前面第3点有讲到,判断一个对象是否可以迭代,其实是通过Symbol.iterator属性来确定的,由此可以创建下面的对象

let obj = {
    *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
    }
};
for (let item of obj) {
    console.log(item);  //1 2 3
}
五.内置迭代器

1.我们平常迭代数组,set和map时,能拿到迭代的值,是因为这些集合中有内置的迭代器,如

let arr = [1, 3, 5];
let set = new Set();
set.add("time");
set.add("user");
set.add("family");
let map = new Map();
map.set("name", "sxt");
map.set("age", 12);
map.set("sister", "andy");

for(let item of arr) {
    console.log(item);  // 1 3 5
}
for(let item of set) {
    console.log(item); //time user family
}
for(let item of map) {
    console.log(item); //["name", "sxt"]  ["age", 12] ["sister", "andy"]
}

2.内置迭代器分为三种

entries()

keys()

values()

3.数组的entries返回的是[索引,值],set的entries是[值,值],因为set的键值是一样的,map的entries是[键名,键值],如:

let arr = [1, 3, 5];
let set = new Set();
set.add("time");
set.add("user");
set.add("family");
let map = new Map();
map.set("name", "sxt");
map.set("age", 12);
map.set("sister", "andy");

for(let item of arr.entries()) {
    console.log(item);  // [0, 1]  [1, 3]  [2, 5]
}
for(let item of set.entries()) {
    console.log(item); //["time", "time"]  ["user", "user"] ["family", "family"]
}
for(let item of map.entries()) {
    console.log(item); //["name", "sxt"]  ["age", 12] ["sister", "andy"]
}

4.数组的keys返回的索引,set的keys返回的还是值,map的keys返回的是值
5.数组,set,map的values返回的都是值

六.向迭代器中传递参数

1.我们可以向迭代器中传递参数

function *createIterator() {
    let first = yield 1;
    let second = yield first + 2;
    yield second + 3;
}

let iterator = createIterator();
console.log(iterator.next());   //{value: 1, done: false}
console.log(iterator.next(4));  //{value: 6, done: false}
console.log(iterator.next(5));  //{value: 8, done: false}
console.log(iterator.next());   //{value: undefined, done: true}

这里的难点是理解右侧的代码会和左边的中断

首次调用next的时候,不管传入什么参数都会被忽略,因为传入的参数会作为yield语句的返回值,而第一次只是yield 1,而没有变量

七.包含return语句的生成器
function *createIterator() {
    yield 1;
    return 133;
    yield 2;
    yield 3;
}

let iterator = createIterator();
console.log(iterator.next());   //{value: 1, done: false}
console.log(iterator.next(4));  //{value: 133, done: true}
console.log(iterator.next(5));  //{value: undefined, done: true}
console.log(iterator.next());   //{value: undefined, done: true}

return会让它提前执行完毕并针对next的调用返回一个值

八.生成器代理

1.即,在一个生成器中调用另外的生成器,有时候,这样的操作会更加的实用

function *create1() {
    yield 1;
    yield 2;
    yield 3;
}

function *create() {
    yield *create1();
    yield true;
}


let iterator = create();
console.log(iterator.next());  //{value: 1, done: false}
console.log(iterator.next());  //{value: 2, done: false}
console.log(iterator.next());  //{value: 3, done: false}
console.log(iterator.next());  //{value: true, done: false}
console.log(iterator.next());  //{value: undefined, done: true}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96201.html

相关文章

  • ES6-迭代器(iterator)和成器(generator) - 什么是迭代器和成器

    摘要:我个人认为迭代器和生成器是新增的特性里面,非常重要的部分,充分地掌握和使用迭代器和生成器,是十分必要和重要的,所以我会写关于二者的一系列文章。 我个人认为迭代器和生成器是es6新增的特性里面,非常重要的部分,充分地掌握和使用迭代器和生成器,是十分必要和重要的,所以我会写关于二者的一系列文章。话不多说,先来了解一下基本概念:一:什么是迭代器 1: 迭代器是一个对象 2: 迭代器有一个属性...

    CollinPeng 评论0 收藏0
  • PHP的迭代器和成器

    摘要:生成器的内部一直在停顿和恢复之间切换,直到循环完成或停顿位置缺点生成器不能满足所有迭代器的需求,因为如果不查询,生成器永远不知道下一个要迭代的值是什么,在生成器中无法后退或前进。 一.迭代器 分析:想一下,如果把集合对象和对集合对象的操作放在一起,当我们想换一种方式遍历集合对象中元素时,就需要修改集合对象了,违背单一职责原则,而迭代器模式将数据结构和数据结构的算法分离开,两者可独立发展...

    sanyang 评论0 收藏0
  • python奇遇记:迭代器和成器

    摘要:来说说迭代器和生成器,还有可迭代对象和生成器表达式。有点绕是不是,其实,一般只要知道可迭代对象以及它是如何实现的就行了,中常常用生成器来代替迭代器,可以说,生成器就是迭代器。 来说说迭代器和生成器,还有可迭代对象和生成器表达式。 之前简单的提到过,一个对象是可迭代的可以理解为能够使用for循环。这样说其实不太准确,某个对象可迭代是因为它内部实现了$__iter__$这个特殊方法。比如在...

    atinosun 评论0 收藏0
  • Python中的可迭代的对象、迭代器和成器

    摘要:本文重点掌握可迭代的对象的定义掌握可迭代对象迭代器与生成器之间的关系和异同熟悉标准库中生成器。二迭代器迭代器介绍迭代器用于从集合中取出元素的对象。若想再次迭代须重建迭代器。迭代器检查方式调用,。区别可迭代的对象不是迭代器。 导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、掌握可迭代的对象的...

    starsfun 评论0 收藏0
  • Python基础-迭代器和成器

    摘要:迭代器迭代器用于循环构建和扩展集合类型逐行遍历文本文件列表推导字典推导和集合推导元组拆包调用函数时,使用拆包实参解释器需要迭代对象时,会自动调用内置的函数,有以下功能检查对象是否实现了方法,如果实现了就调用它,获取一个迭代器。 迭代器 迭代器用于: for 循环 构建和扩展集合类型 逐行遍历文本文件 列表推导、 字典推导和集合推导 元组拆包 调用函数时, 使用 * 拆包实参 解释器...

    objc94 评论0 收藏0
  • ES6-迭代器(iterator)和成器(generator)- 迭代器和成器的高级用法

    摘要:在生成器中使用语句生成器也是函数,所以它也可以使用语句。只是由于生成器本身的特性,其内部的的行为会和一般函数有些差别。 前面2篇系列文章讲解了迭代器和生成器的最常用,最基础的用法;这篇来讨论迭代器和生成器的一些稍稍高级一点的用法: 1: 给迭代器的next()方法传参 2: 从迭代器中抛出错误 3: 在生成器中使用return语句 4: 委托生成器(组合生成器或者生成器组合?) 1: ...

    Edison 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<