ES6的迭代器与迭代协议Symbol.iterator

前言

ES6新增了两个协议:

可迭代协议:对象必须具有Symbol.Iterator属性,属性值为一个函数,当这个对象被迭代时,就会调用该函数,返回一个迭代器。

迭代器协议:描述了迭代器对象的具体规则。

迭代器

迭代器,它是用于访问集合类的标准访问方法,它可以把访问逻辑从不同类型集合中抽象出来,从而避免向外部暴露集合内部的结构。

比如我们访问一个数组可能使用for循环或者map,foreach,filter等for(int i=0; i

在js中,当我们要迭代集合(指数组)的时候,我们利用ES6为Array类增加的迭代器属性(iterator),该属性的值为一个函数,该函数返回一个迭代器对象。而Array类的iterator属性可以通过Symbol.iterator来访问。我们执行这个函数来生成该数组的迭代器。

const arr = ['a','b','c','d']
const arrIterator = arr[Symbol.iterator]();
ES6的迭代器与迭代协议Symbol.iterator_第1张图片

关于什么是Symbol,可以看本文附录。

我们已经得到了数组的迭代器,如果我们需要依次获得数组中的值,我们需要不断地调用迭代器的next方法。

arrIterator.next();
// {value: 'a', done: false}

可以看见执行next方法后返回了数据对象,value键对应的是数组的元素,done代表的时候迭代器是否已经迭代到了数组长度的最后下标。

ES6的迭代器与迭代协议Symbol.iterator_第2张图片

当迭代器迭代到数组长度以外之后,返回了{value: undefined, done: true}

我们也可以这么写:

for (const n of arrIterator) {
    console.log(n)
}
// a
// b
// c
// d
// e

总结一下:

  • 在Js中迭代器对象实现了可迭代协议,迭代器对象由Symbol.iterator属性的值返回。

  • Symbol.iterator属性的值是一个函数,它返回一个迭代器对象。

  • 迭代器指的是拥有next方法的对象。

  • 该next方法必须返回一个带有value和done的对象。

除了Symbol.iterator,ES6中另外提供三种获取数组迭代器的方法

var arr = ['a','b','c']

entries

const iterator = arr.entries();
iterator.next(); // {value: [0,'a'], done: false}
...
iterator.next(); // {value: undefined, done: true}

可以看到entries提供的迭代器返回的结构与Symbol.iterator相似。只是value键对应的值是,包含当前迭代的数组元素的下标和值的数组。

keys

const iterator = arr.keys()
iterator.next()
// {value: 0, done: false}
...
iterator.next()
// {value: undefined, done: true}

value值是当前迭代的数组元素的下标。

values

const iterator = arr.values()
undefined
iterator.next()
// {value: 'a', done: false}
...
iterator.next()
// {value: undefined, done: true}

value值是当前迭代的数组元素。

附录-Symbol

Symbol是es6新增的类型,它是一个基本类型。

  • symbol属性值对应的值是唯一的,这解决了命名冲突的问题,类似于id的作用。

  • symbol值不能与其他数据进行计算,包括与字符串拼接。

  • for/in ,for/of遍历时不会遍布symbol属性

我们知道symbol可以作为属性值存在。并且它具有唯一的特性,举个栗子:直接let s = Symbol();测试s就是Symbol类型了。怎么说他是唯一的呢?
let s = Symbol(); let ss = Symbol(); s == ss ; 结果是false;或者
let s = Symbol('a'); let ss = Symbol('a'); s == ss ; 结果是false
有人会好奇Symbol('a')里面的参数a又是怎么回事呢?字符串a表示一种修饰,对你当前创建的Symbol类型的一种修饰,作为区分使用,否则当你创建多个Symbol数据时,容易混淆。
现在我们回过头说Iterotor是symbol的内置符号,而字符串a是自定义的符号。

附录-for of

条件语句,可以理解为JavaScript解释器在源代码中会经过不同分支路径。而循环语句则是把这些路径弯曲又折回起点,以重复执行代码中的某部分。

es6定义了一个新循环语句:for/of。

for of 与 for in不相同 (in输出的是下标,of输出的是元素)

for/of循环是专门用于可迭代对象的,什么是可迭代对象呢?

我们前文提到具有symbol.iterator属性的对象就是可以迭代的。而这个对象就是可迭代对象。

对象本身默认是不可迭代的。运行时尝试对常规对象使用for/of会抛出TypeError:

ES6的迭代器与迭代协议Symbol.iterator_第3张图片

附录-JS中 可迭代的数据类型

Array

Set

Map

WeakMap

WeakSet

可以使用for of或new Set(传入参数的数据类型)检验

你可能感兴趣的:(JavaScript,算法,javascript,前端)