ES6 中的 iterator

【简介】

遍历器/迭代器。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。这种数据结构是“可遍历的”(iterable)。

如何判断是否可遍历?

 typeof target[Symbol.iterator] // function

【作用】

  1. 为各种数据结构,提供一个统一的、简便的访问接口;

  2. 使得数据结构的成员能够按某种次序排列;

  3. ES6 创造了一种新的遍历命令for...of 循环,Iterator 接口主要供for...of消费。

【遍历】

const colors = ["red", "green", "blue"]
for (var i = 0, len = colors.length; i < len; i++) {
  console.log(colors[i])
}
  1. 追踪下标位置,
  2. 判断循环何时停止。

自定义 iterator

function createIterator(items) {
  var i = 0
  return {
    next: function () {
      var done = (i >= items.length)
      var value = !done ? items[i++] : undefined
      return {
        done: done,
        value: value,
      }
    }
  }
}

var iterator = createIterator([1, 2, 3])
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

Iterator 的遍历过程:

1、创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。

2、第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。

3、不断调用指针对象的next方法,直到它指向数据结构的结束位置。

虽然是比 for 循环简单了些,但手动写个 iterator 太麻烦了,所以ES6 推出 generator ,方便创建 iterator。也就是说,generator 就是一个返回值为 iterator 的函数。

【generator 和 iterator】

function* createIterator() {
  yield 1
  yield 2
  yield 3
}

let iterator = createIterator()
console.log(iterator.next().value)
console.log(iterator.next().value)
console.log(iterator.next().value)

Generator:ES6 提供的一种异步编程解决方案。

执行 Generator 函数会返回一个 iterator 对象,通过这个对象可以依次遍历 Generator 函数内部的每一个状态。

【for…of 和 iterator】

const colors = ["red", "green", "blue"];
for (let color of colors) {
  console.log(color);
}

当使用for…of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口,并调用Symbol.iterator方法,返回该对象的默认遍历器。

for…of循环可以使用的范围包括数组、Set 和 Map、类似数组对象(arguments、DOM NodeList、 Generator、字符串)。

【内置的 iterator】

ES6 的有些数据结构原生具备 Iterator 接口(比如数组),即不用任何处理,就可以被 for…of 循环遍历。

原因在于,这些数据结构原生部署了Symbol.iterator属性,另外一些数据结构没有(比如对象)。

凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。

原生具备 Iterator 接口的数据结构如下。

Array、Map、Set、String、arguments 、NodeList

// Array iterator
const heros = [‘Tony‘, ‘Steve‘, ‘Natasha‘, ‘Banner‘, ‘Thor‘]
for (const hero of heros) {
  console.log(hero)
}

// Map iterator
const sex = ‘male‘
const userMap = new Map([
  [‘name‘, ‘Stark‘],
  [48, ‘age‘ ],
  [‘gender‘, sex]
])

for (let entry of userMap.entries()) {
  console.log(entry)
}

for (let key of userMap.keys()) {
  console.log(key)
}

for (let value of userMap.values()) {
  console.log(value)
}

const numberSet = new Set([1, 2, 2, 3, 4, 4, 5])
for (let entry of numberSet.entries()) {
  console.log(entry)
}

for (let key of numberSet.keys()) {
  console.log(key)
}

for (let value of numberSet.values()) {
  console.log(value)
}

// String iterator
const str = ‘ca ?? r‘for (const c of str) {
  console.log(c)
}

// arguments iterator
function getUserInfo (name, male, age, hobby) {
  console.log(arguments.length)
  for (const arg of arguments) {
    console.log(arg)
  }
}
getUserInfo(‘code monkey‘, ‘male‘, ‘28‘, ‘make money‘)

一个类数组对象如果要具备可被 for...of 循环调用的 Iterator 接口,就必须在Symbol.iterator的属性上部署遍历器生成方法。

// Array alike iterator
const arrAlike = {
  0: ‘a‘,
  1: ‘b‘,
  2: ‘c‘,
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
}
for (const item of arrAlike) {
  console.log(item) // a b c
}

// 普通对象部署数组的Symbol.iterator方法,并无效果。
const obj = {
  a: ‘a‘,
  b: ‘b‘,
  c: ‘c‘,
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
}

for (const item of obj) {
  console.log(item) // undefined undefined undefined
}

注:普通对象部署数组的Symbol.iterator方法,并无效果。因为数组,Map和类数组对象等结构中的成员都是有顺序的,

即都是线性的结构,而对象各成员并没有一个确定的顺序,所以遍历时先遍历谁后遍历谁并不确定。

【解构、扩展运算 和 Iterator】

对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法。

扩展运算符(...)也会调用默认的 Iterator 接口。

const set = new Set().add(‘a‘).add(‘b‘).add(‘c‘)
const [x, y] = set
console.log(x, y)

const [first, ...rest] = set
console.log(first, rest)

const str = ‘hello‘
console.log([...str])

const arr = [‘b‘, ‘c‘];
console.log([‘a‘, ...arr, ‘d‘])

【小结】

1. Iterator 就是为了提供一种统一的接口机制。任何的数据结构,只要部署了Iterator接口,便可以使用 for…of 来遍历。

2. es6中有三类结构生来就具有Iterator接口:数组、类数组对象、Map和Set结构。

3. String、类数组对象、函数的arguments对象和nodeList 对象的遍历以及generator的使用、扩展运算符和解构赋值的操作也会调用到 iterator。

4. 对象不具备 iterator 接口,但是可以通过部署 Symbol.iterator 属性来使对象可遍历。

原文地址:https://www.cnblogs.com/wx1993/p/9047052.html

时间: 2024-08-29 07:03:45

ES6 中的 iterator的相关文章

理解ES6中的Iterator

一.为什么使用Iterator 我们知道,在ES6中新增了很多的特性,包括Map,Set等新的数据结构,算上数组和对象已经有四种数据集合了,就像数组可以使用forEach,对象可以使用for...in.. 进行遍历一样,是不是随着Map和Set的出现也应该给这两种集合一个遍历方法呢?如果这样的话js的方法对象就太多了,既然这四种集合都是需要遍历的,那么完全可以用一个统一的访问机制.于是乎Iterator应运而生. 二.Iterator是什么 Iterator是一个访问机制,同时是一个接口,可以实

ES6中的Iterator和for...of

先说说数组遍历的几种方法吧: 1,for循环: 缺点:写法麻烦2,内置forEach方法; 缺点:不能跳出循环;break和return都不能;3,for...in;    缺点:数组的键名是数字,但是for...in循环是以字符串作为键名"0"."1"."2"等等.for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键.某些情况下,for...in循环会以任意顺序遍历键名.总之,for...in循环主要是为遍历对象

ES6中的迭代器(Iterator)和生成器(Generator)

前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 本文将详细介

使对象具有ES6中Iterator接口的实现方法

es6中只有具有iterator接口的数组或者类数组(arguments)都可以使用for of来循环,但是对于对象来说不行,可以利用迭代器中的原理来给对象生成一个迭代器,实现让对象可以使用for of 1 var j={ 2 name:'小红', 3 age:18 4 } 5 //给j对象添加一个iterator接口 6 j[Symbol.iterator]=function(){ 7 //使用object.keys()方法把j对象中的k值读取出来存在数组当中 8 var arr=Object

ES6中的迭代器(Iterator)和生成器(Generator)(一)

用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 一.引入 下面是一段标

ES6中的Symbol类型

前面的话 ES5中包含5种原始类型:字符串.数字.布尔值.null和undefined.ES6引入了第6种原始类型--Symbol ES5的对象属性名都是字符串,很容易造成属性名冲突.比如,使用了一个他人提供的对象,想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突.如果有一种机制,保证每个属性的名字都是独一无二的,这样就从根本上防止了属性名冲突.这就是ES6引入Symbol的原因,本文将详细介绍ES6中的Symbol类型 创建 Symbol 值通过Symbol函数生成.这就是说,

ES6中的Set和Map集合

前面的话 在ES6标准制定以前,由于可选的集合类型有限,数组使用的又是数值型索引,因而经常被用于创建队列和栈.如果需要使用非数值型索引,就会用非数组对象创建所需的数据结构,而这就是Set集合与Map集合的早期实现.本文将详细介绍ES6中的set和map集合 引入 Set集合是一种无重复元素的列表,开发者们一般不会逐一读取数组中的元素,也不太可能逐一访问Set集合中的每个元素,通常的做法是检测给定的值在某个集合中是否存在 Map集合内含多组键值对,集合中每个元素分别存放着可访问的键名和它对应的值,

ES6中的类

前面的话 大多数面向对象的编程语言都支持类和类继承的特性,而JS却不支持这些特性,只能通过其他方法定义并关联多个相似的对象,这种状态一直延续到了ES5.由于类似的库层出不穷,最终还是在ECMAScript 6中引入了类的特性.本文将详细介绍ES6中的类 ES5近似结构 在ES5中没有类的概念,最相近的思路是创建一个自定义类型:首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型 function PersonType(name) { this.name = name; } Person

es6 javascript的Iterator 和 for...of 循环

1 Iterator( 遍历器) 的概念 JavaScript 原有的表示" 集合" 的数据结构, 主要是数组( Array) 和对象( Object), ES6 又添加了 Map 和 Set. 这样就有了四种数据集合, 用户还可以组合使用它们, 定义自己的数据结构, 比如数组的成员是 Map, Map 的成员是对象. 这样就需要一种统一的接口机制, 来处理所有不同的数据结构. 遍历器( Iterator) 就是这样一种机制. 它是一种接口, 为各种不同的数据结构提供统一的访问机制.