Iterator 是一个接口 为各种数据结构统一封装了一个遍历方法(只要部署了 Iterator 接口)主要给 for of 去消费的
Iterator 作用
- 统一了历史上各种数据结构的访问接口
- 提供了一个 for-of 命令来循环
以上 有几个点
- 接口? 如何实现
- 统一数据结构? 如何不统一了
Iterator 接口
在 js 语言中 没有接口这么一个概念 我们尝试理解为一个迭代器对象
- 迭代器对象结构
next: function() { return { value: xxx, // 结果值 done: true || false // 来检测是否遍历完 } },复制代码
- 我们模拟实现下
function makeIterator(list) { var index = 0 return { // 返回一个可迭代的对象 next:function() { return index >list.length? { value: undefined, done: true } : { value: list[index++], done: false } } } } var it = makeIterator(['a', 'b', 'c']); console.log(it.next()) //{value: "a", done: false} console.log(it.next()) //{value: "b", done: false} console.log(it.next()) //{value: "c", done: false} console.log(it.next()) //{ value: undefined, done: true}复制代码
那这个跟 for-of 有啥关系 跟统一了数据结构有啥关系那?带着问题往下看
看下场景
var arr = ['a','b','c'] 遍历数组 arr 能想到的方法
- case1
for(let i=0; i<arr.length; i++) { console.log(arr[i]) }复制代码
- case2
arr.forEach(item => { console.log(item) })复制代码
- case3
for(var i in arr) { console.log(i arr[i]) // 0 1 2 // a b c }复制代码
- case4for(var i of arr) { console.log(i) // a b c }
var str ='abc' 遍历字符串同样的这么多 case
会发现遍历一个资源 有很多方法 有没有一个统一的方法 for-of 来了
for-of
阮一峰ES6 借鉴 C++、Java、C# 和 Python 语言,引入了 for...of 循环,作为遍历所有数据结构的统一的方法.
for-of 不是对所有资源都能遍历 只有实现了(通过 Iterator 接口包装的)Iterator 接口的才能使用 for-of (换句话说就是 一个资源上有了 Iterator 接口(Symbol.iterator) 就能使用 for-of 来使用了)
- 普通对象 不能 被使用 因为普通对象上没有 Symbol.iterator 属性 // 普通数组使用报错
- 字符串可以使用 字符串上有 Symbol.iterator 默认属性
- 普通数组可以使用 因为数组默认带了 Symbol.iterator 属性
问题来了 普通对象如何才能使用?
普通对象 被 for-of 消费
- 我们来模拟实现下
只要将普通对象包装一个 Symbol.iterator 接口就行
var markObjectIterator = { items: {a:1,b:2,c:3}, [Symbol.iterator]: function() { var self = this; var i = 0; return { next: function () { var done = (i >= Object.keys(self.items).length); var value = !done ? self.items[Object.keys(self.items)[i++]] : undefined; return { done: done, value: value }; } }; }} for(var item of markObjectIterator) { console.log(item) }复制代码
总结
- 熟悉 es6 代码
- code 一个简易迭代器接口
- 实现一个 for-of 消费的简易的可迭代对象
- 对 Symbol.iterator 下章详解