ES6 迭代器与可迭代对象的实现(2)

let collection = { items: [11,22,33], *[Symbol.iterator]() { for (let item of this.items){ yield item } } } console.log(isIterator(collection)) // true for (let item of collection){ console.log(item) // 11 22 33 }

数组 items 是可迭代对象,collection 对象通过给Symbol.iterator属性赋值也成为可迭代对象。

3.3 for-of

注意到上个栗子使用了for-of代替索引循环,for-of是 ES6 为可迭代对象新加入的特性。

思考一下for-of循环的实现原理。

对于使用for-of的可迭代对象,for-of每执行一次就会调用这个可迭代对象的 next( ),并将返回结果存储在一个变量中,持续执行直到可迭代对象 done 属性值为 false。

// 迭代一个字符串 let str = 'somestring' for (let item of str){ console.log(item) // s o m e s t r i n g }

本质上来说,for-of调用 str 字符串的Symbol.iterator属性方法获取迭代器(这个过程由 JS 引擎完成),然后多次调用 next( ) 方法将对象 value 值存储在 item 变量。

将for-of用于不可迭代对象、null 或 undefined 会报错!

3.4 展开运算符(...)

ES6 语法糖展开运算符(...)也是服务于可迭代对象,即只可以“展开”数组、集合、字符串、自定义可迭代对象。

以下栗子输出不同可迭代对象展开运算符计算的结果:

let str = 'somestring' console.log(...str) // s o m e s t r i n g let set = new Set([1, 2, 2, 5, 8, 8, 8, 9]) console.log(set) // Set { 1, 2, 5, 8, 9 } console.log(...set) // 1 2 5 8 9 let map = new Map([['name', 'jenny'], ['id', 123]]) console.log(map) // Map { 'name' => 'jenny', 'id' => 123 } console.log(...map) // [ 'name', 'jenny' ] [ 'id', 123 ] let num1 = [1, 2, 3], num2 = [7, 8, 9] console.log([...num1, ...num2]) // [ 1, 2, 3, 7, 8, 9 ] let udf console.log(...udf) // TypeError: undefined is not iterable

由以上代码可以看出,展开运算符(...)可以便捷地将可迭代对象转换为数组。同for-of一样,展开运算符(...)用于不可迭代对象、null 或 undefined 会报错!

四. 默认迭代器

ES6 为很多内置对象提供了默认的迭代器,只有当内建的迭代器不能满足需求时才自己创建迭代器。

ES6 的 三个集合对象:Set、Map、Array 都有默认的迭代器,常用的如values()方法、entries()方法都返回一个迭代器,其值区别如下:

entries():多个键值对

values():集合的值

keys():集合的键

调用以上方法都可以得到集合的迭代器,并使用for-of循环,示例如下:

/******** Map ***********/ let map = new Map([['name', 'jenny'], ['id', 123]]) for(let item of map.entries()){ console.log(item) // [ 'name', 'jenny' ] [ 'id', 123 ] } for(let item of map.keys()){ console.log(item) // name id } for (let item of map.values()) { console.log(item) // jenny 123 } /******** Set ***********/ let set = new Set([1, 4, 4, 5, 5, 5, 6, 6,]) for(let item of set.entries()){ console.log(item) // [ 1, 1 ] [ 4, 4 ] [ 5, 5 ] [ 6, 6 ] } /********* Array **********/ let array = [11, 22, 33] for(let item of array.entries()){ console.log(item) // [ 0, 11 ] [ 1, 22 ] [ 2, 33 ] }

此外 String 和 NodeList 类型都有默认的迭代器,虽然没有提供其它的方法,但可以用for-of循环

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/b1a6e21e1ebf189c5a091afb2d4d6cae.html