ES6语法(十二)Iterator

Iterable

处理集合中的每个项是很常见的操作。JavaScript提供了许多迭代集合的方法,从简单的for循环到map()和filter()。迭代器和生成器将迭代的概念直接带入核心语言,并提供了一种机制来自定义for…of循环的行为。

如果对MDN这个描述理解不是很到位的话,可以看接下来这个示例:

let authors = {
	allAuthors: {
    	fiction: ['Agla', 'Skks', 'LP'],
    	scienceFiction: ['Neal', 'Arthru', 'Ribert'],
    	fantasy: ['J.R.Tole', 'J.M.R', 'Terry P.K']
  	},
  	Addres: []
}

这个数据结构是汇总了所有作者,每个作者按创作性质进行了分类。如果想获取所有作者的名单,该怎么做呢?

for(let author of authors){
	console.log(author ) // Uncaught TypeError: authors is not iterable
}

Iterator

Iterator是ES6中用来实现自定义遍历的接口,按照上述的示例,可以实现这个接口:

authors[Symbol.iterator] = function () {
  let allAuthors = this.allAuthors
  let keys = Reflect.ownKeys(allAuthors)
  let values = []
  return {
    next () {
      if (!values.length) {
        if (keys.length) {
          values = allAuthors[keys[0]]
          keys.shift()
        }
      }
      return {
        done: !values.length,
        value: values.shift()
      }
    }
  }
}

这个代码在数据结构上部署了Iterator接口,我们就可以用for…of来遍历代码了:

for(let value of authors){
	console.log(`${value}`)
}

从代码上看到了自定义遍历器的强大,但是怎么理解Iterator呢?首先,要理解几个概念:可迭代协议和迭代器协议。
1.迭代器协议

属性
next返回一个对象的无参函数,被返回对象拥有两个属性:done和value

这是两个概念:可迭代协议和迭代器协议。通俗的讲,迭代器协议要求符合以下条件:
1.首先,他是一个对象
2.其次,这个对象包含一个无参函数next
3.最后,next返回一个对象,对象包含done和value属性。其中done表示遍历是否结束,value返回当前遍历的值。

如果next函数返回一个非对象值(比如false和undefined)会展示一个TypeError(“iterator.next() return a non-object value”)的错误

2.可迭代协议
可迭代协议允许JavaScript对象定义或定制它们的迭代行为,例如在一个for…of结构中什么值可以被循环(得到)。一些内置类型都是内置的可迭代类型并且有默认的迭代行为,比如Array or Map,另一类型则不是(比如Object)。
为了变成可迭代对象,一个对象必须实现@@iterator方法,意思是这个对象(或者它的原型链prototype chain上的某个对象)必须有一个名字是Symbol.iterator的属性:

属性
[Symbol.iterator]返回一个对象的 无参函数,被返回对象符合迭代器协议

如果让一个对象是可遍历的,就要遵循可迭代协议,该协议要求对象要部署一个Symbol.iterator为key的键值对,而value就是一个无参函数,这个函数返回的对象要遵循迭代器协议。
Generator
熟悉了Generator之后,发现它是天然满足可迭代协议的。上述的代码可以用Generator实现:

authors[Symbol.iterator] = function * () {
  let allAuthors = this.allAuthors
  let keys = Reflect.ownKeys(allAuthors)
  let values = []
  while (1) {
    if (!values.length) {
      if (keys.length) {
        values = allAuthors[keys[0]]
        keys.shift()
        yield values.shift()
      } else {
        return false
      }
    } else {
      yield values.shift()
    }
  }
}

同一个场景,同一个数据结构,写法确实不同的,利用Generator就不再需要显示的写迭代器协议了(next方法和包含done、value属性的返回对象。)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值