简介

  迭代器是一种设计模式,可在容器对象 如 链表、数组上遍历,无需关心容器对象的内存分配的实现细节。简单的理解就是可以一个一个的依次拿到其中的数据,类似一个移动的指针,但是会告诉我们什么时候结束。这样我们可以拿到数据之后可以做一些我们需要做的事情。

js 中的迭代器是什么样子的

  在javascript 中迭代器是一个特殊对象,这个迭代器对象有一个next()方法,每次调用都返回一个对象(结果对象)。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,如果已经迭代到序列中的最后一个值,则它为 true。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每调用一次next()方法,都会返回下一个可用的值,类似下面这个对象的结构。

{
next: function () {
return {
value:'',
done: true / false
}
}
}

迭代协议

  随着javascript 语言的能力进一步提升,新增了一些新的数据类型 如 Map、Set、WeakMap 等,为了这些不同的数据结构,可以统一的迭代,es6 增加了迭代协议这个东西。

迭代协议并不是新的内置实现或语法,而是协议。这些协议可以被任何遵循某些约定的对象来实现。

迭代协议具体分为两个协议:可迭代协议和迭代器协议。

简单的理解就是在js 中任何对象只要满足迭代协议就可以遍历

可迭代协议

要成为可迭代对象, 一个对象必须实现 @@iterator 方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator 访问该属性:

简单的理解,你想让一个东西可以遍历,那么这个东西要有一个 @@iterator ,这个属性可以通过Symbol.iterator 访问

属性

[Symbol.iterator]

一个无参数的函数,其返回值为一个符合迭代器协议的对象。

迭代器协议

迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式。当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。

只有实现了一个拥有以下语义(semantic)的 next() 方法,一个对象才符合迭代器协议:

属性

next

一个无参数函数,返回一个应当拥有以下两个属性的对象:

done(boolean)

next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value,如果返回了一个非对象值(比如 false 或 undefined),则会抛出一个 异常("iterator.next() returned a non-object value")。

迭代过程

当一个对象需要被迭代的时候(比如被写入一个 for...of 循环时),首先,会不带参数调用它的 @@iterator 方法( 此时返回的是结构是这样的 { next: function () {}}),然后使用此方法返回的迭代器获得要迭代的值(其实就是不断的调用这个next()方法)

迭代总结

迭代协议可以总结为,一个东西要遍历,必须满足可迭代协议跟迭代器协议

  • 可迭代协议:这个对象必须有@@iterator,可以通过Symbol.iterator 访问
  • 迭代器协议:是一个对象,这个对象的next() 函数返回一个对象,这个对象包括两个属性,一个是value,一个是done(boolean,是否是最后一个元素,done 为 true 时 value 可省略)

也就是说 迭代器对象本质上,就是一个指针对象。通过指针对象的next(),用来移动指针。

自定义迭代

对象是没有实现迭代器,所以不能遍历对象,为了可以实现对象的遍历,我们需要在对象上实现上面说的迭代器,通常有两种写法,一种是传统的写法,这种需要自己去控制内部的状态,另外一种是利用生成器函数返回的Generator的迭代器来实现,代码如下:

传统写法

let obj = {
name: 'joel',
adress: 'gz',
[Symbol.iterator]: () => {
// 这里不要用this, 因为是return fn, this 会丢失
let index = -1, atrrList = Object.keys(obj);
const objIterator = {
next: () => {
let result = ''
index++
if (index < atrrList.length) {
result = {
value: atrrList[index],
done: false
}
} else {
result = {
done: true
}
}
return result
}
}
return objIterator
}
} for (const item of obj) {
console.log('atrrs:' + item + ',value:' + obj[item])
}

生成器函数写法

// 为不可迭代的对象添加迭代器
let obj = {
a: 1,
b: 2
}
obj[Symbol.iterator] = function* () {
let keys = Object.keys(obj);
//取到key值的长度
let len = keys.length;
//定义循环变量
let n = 0;
//条件判断
while (n <= len - 1) {
yield { k: keys[n], v: obj[keys[n]] };
n++
}
}
//返回的是个对象的key和value
for (let { k, v } of obj) {
console.log(k, v);
}

其他相关如内置可迭代对象、用于可迭代对象的语法、接受可迭代对象的内置api 等 请点击 这里

javascript 之迭代器的更多相关文章

  1. JavaScript设计模式 - 迭代器模式

    迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺 ...

  2. javascript设计模式——迭代器模式

    前面的话 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示.迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也 ...

  3. javascript设计模式-迭代器模式(Iterator)

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. ES6入门十:iterator迭代器

    迭代模式 ES6迭代器标准化接口 迭代循环 自定义迭代器 迭代器消耗 一.迭代模式 迭代模式中,通常有一个包含某种数据集合的对象.该数据可能存在一个复杂数据结构内部,而要提供一种简单的方法能够访问数据 ...

  5. MongoDB学习笔记-游标

    理解MongoDB的游标有两种维度:客户端和服务器端.下面将从这两方面来说明. 客户端 find方法返回值是一个游标.可以通过游标来对最终结果进行控制.比如限制结果数量,略过某一部分,根据任意键按任意 ...

  6. 01快速入门-04-Map、Set和iterable(ES6)

    1.Map 我们知道,在JS中其实对象的方式就跟Java中的Map极为相似,即键值对的方式.JS中,key必须是字符串,实际上Number等值作为key也是合理的,所以为了解决这个问题,在最新的ES6 ...

  7. MongoDB系列一(查询).

    一.简述 MongoDB中使用find来进行查询.查询就是返回一个集合中文档的子集,子集合的范围从0个文档到整个集合.默认情况下,"_id"这个键总是被返回,即便是没有指定要返回这 ...

  8. es6学习笔记--Interator和Generator(以及for-of的用法)

    这几天学习了遍历器和生成器,看着资料学,有点雾里缭绕的感觉,让人忍不住放弃,还好多看了好几遍,怼着资料里的例子让自己学会了Interator和Generator.   Interator,中文简称:遍 ...

  9. Observable详解

    Observable详解 rxjs angular2 在介绍 Observable 之前,我们要先了解两个设计模式: Observer Pattern - (观察者模式) Iterator Patte ...

随机推荐

  1. [考试总结]noip模拟7

    为啥博客园 \(\LaTeX\) 老挂???! \(\huge{\text{菜}}\) 刚开始写 \(T1\) 的时候,在看到后缀前缀之后,直接想到 \(AC\) 自动机,在画了半个 \(trie\) ...

  2. 第二篇 -- Go语言转义字符与变量声明

    上节我们讲了GO语言的环境搭建以及创建了Hello World程序.今天学习一下Go语言基础语法 开发前准备 1. 首先创建一个Project02 2. 在Project02下面新建一个test1.g ...

  3. HTML5 socket

    client: <!DOCTYPE html> <html> <head> <title></title> <meta http-eq ...

  4. PASS-单组目标值法的样本量计算

    临床试验的参数估计中,评价指标有确定的估计目标 ,临床试验目的需通过参数估计(含相应的可信区间估计)的方法证明评价指标不低于目标值时,可根据单组目标值法样本量公式计算. 例:欲证明器械A的诊断准确性非 ...

  5. Samba 远程命令执行漏洞(CVE-2017-7494)

    该漏洞影响Samba 3.5.0之后的所有版本,在4.6.4/4.5.10/4.4.14修复了这个漏洞 use exploit/linux/samba/is_known_pipename set rh ...

  6. SpringCloud升级之路2020.0.x版-5.所有项目的parent与spring-framework-common说明

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 源代码文件:htt ...

  7. 群晖NAS网络存储服务器防盗防小偷

    群晖NAS网络存储服务器防盗防小偷 根据群晖NAS的实际测量外形尺寸到淘宝网邮购金属  配电箱(弱电箱). 把配电箱(弱电箱)用粗螺丝固定到机柜或墙壁上. 把群晖NAS用密码纯铜挂锁锁在配电箱(弱电箱 ...

  8. 小白学习vue第三天,从入门到精通(computed计算属性)

    computed计算属性 <body> <div id="app"> <div>{{myName}}</div> </div& ...

  9. Bugku-你必须让他停下来

    这道题使用burpsuite抓包就能做,一开始抓包发到repeater之后flag不一定可以直接得到,原因是flag藏在特定的那张图片后面,我们一直go到那张图片便可以得到flag. 进入题目给的网址 ...

  10. Spring对Controller、Service、Dao进行Junit单元测试总结

    测试类注解 @RunWith(SpringRunner.class) @SpringBootTest(classes={DemoApplication.class}) 以Controller层的的单元 ...