当前位置: 首页 > 后端技术 > Node.js

ES6新特性:Iterables和iterators简介

时间:2023-04-03 12:54:25 Node.js

为了方便集合数据的遍历,ES6中引入了迭代的概念。它为我们提供了一种更方便的数据遍历手段。让我们一起学习。什么是迭代迭代又叫遍历,就像数据库游标一样,一步步遍历一个集合或对象的数据。根据ES6的定义,迭代主要由三部分组成:Iterable首先看一下Iterable的定义:interfaceIterable{[Symbol.生成迭代器的工厂方法。IteratorinterfaceIterator{next():IteratorResult;}可以从Iterable构建Iterator。Iterator是一个类似于游标的概念,可以通过next访问IteratorResult。IteratorResultIteratorResult是每次调用next方法时得到的数据。接口IteratorResult{值:任何;done:boolean;}在IteratorResult中,除了一个表示要获取数据的值外,还有一个表示是否遍历完成的done。Iterable是一个接口,通过它我们可以连接数据提供者和数据消费者。可迭代对象称为数据提供者。对于数据消费者来说,除了调用next方法获取数据外,还可以使用for-of或者...扩展操作符进行遍历。for-of示例:for(constxof['a','b','c']){console.log(x);}...扩展运算符的示例:constarr=[...newSet(['a','b','c'])];Iterable对象在ES6中,以下类型可以称为Iterable对象:ArraysStringsMapsSetsDOM首先看一个Arrays的情况,如果我们有一个Arrays,可以通过Symbol.iterator的key获取Iterator:>constarr=['a','b','c'];>constiter=arr[Symbol.iterator]();>iter.next(){value:'a',done:false}>iter.next(){value:'b',done:false}>iter.next(){value:'c',done:false}>iter.next(){value:undefined,done:true}一个更简单的方法是使用for-of:for(constxof['a','b']){console.log(x);}//Output://'a'//'b'看一个遍历String的情况,String的遍历是以Unicode代码点区分:for(constxof'a\uD83D\uDC0A'){console.log(x);}//Output://'a'//'\uD83D\uDC0A'(鳄鱼表情符号)在上面的例子,String的基本类型在遍历的时候会自动转换成String对象。Maps通过遍历条目实现:constmap=newMap().set('a',1).set('b',2);for(constpairofmap){console.log(pair);}//Output://['a',1]//['b',2]还记得前面提到的WeakMaps吗?WeakMap、WeakSet和Map的区别在于WeakMap的key只能是Object对象,不能是基本类型。为什么会有WeakMap?对于JS中的Map,通常需要维护两个数组,key存放在第一个数组中,value存放在第二个数组中。每次添加和删除项,都需要同时操作两个数组。这种实现有两个缺点。第一个缺点就是每次查找的时候都需要遍历key数组,然后找到对应的索引,然后用索引从第二个数组中找到value。第二个缺点是key和value是强绑定的,即使key不再使用也不会被垃圾回收。因此引入了WeakMap的概念。在WeakMap中,key和value没有这么强的绑定关系。如果密钥不再被使用,它可以被垃圾收集器回收。因为弱引用关系,weakMap不支持key遍历。如果要遍历key,请使用Map。看一下Set的遍历:constset=newSet().add('a').add('b');for(constxofset){console.log(x);}//输出://'a'//'b'我们也可以遍历arguments对象:functionprintArgs(){for(constxofarguments){console.log(x);}}printArgs('a','b');//Output://'a'//'b'对于大多数DOM也是可遍历的:for(constnodeofdocument.querySelectorAll('div')){···}普通对象不可遍历对象是字面量创建的对象。这些对象虽然也有key-value内容,但是不可遍历。为什么?因为Array、Map、Set等可遍历对象也是普通对象的特例。如果普通对象是可遍历的,这会导致一些可遍历对象的遍历发生冲突。for(constxof{}){//TypeErrorconsole.log(x);}虽然不能直接遍历普通对象,但是我们可以通过objectEntries方法遍历普通对象。先看objectEntries的实现:functionobjectEntries(obj){letiter=Reflect.ownKeys(obj)[Symbol.iterator]();return{[Symbol.iterator](){返回这个;},next(){let{done,value:key}=iter.next();如果(完成){返回{完成:真};}return{value:[key,obj[key]]};}};}我们通过Reflect.ownKeys()反射得到对象中的迭代器。然后用这个迭代器遍历普通对象。看具体用法:constobj={first:'Jane',last:'Doe'};for(const[key,value]ofobjectEntries(obj)){console.log(`${key}:${value}`);}//Output://first:Jane//last:DoecustomiterablesIn除了ES6中默认的iterables,我们还可以自定义iterables。由于iterables是一个接口,我们只需要实现它。让我们看一个迭代的例子:functioniterateOver(...args){letindex=0;constiterable={[Symbol.iterator](){constiterator={next(){if(index