【问题标题】:Do all JavaScript Iterables have a next() method?是否所有的 JavaScript Iterables 都有 next() 方法?
【发布时间】:2019-10-02 19:39:12
【问题描述】:

我正在从https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators 学习 Iterables,它清楚地表明 Array 是 Iterable。在 chrome 控制台中检查,我们可以看到它有Symbol.iterator,我们可以在上面运行for..of

但数组似乎不遵循迭代器模式,即拥有 next() 方法,我有点明白,因为您无法重置迭代器,这将严重限制数组。

但是我无法从文档中确定哪些 Iterables 具有完整的实现 (next()),哪些没有,或者我在这里缺少一个基本概念。

我错过了什么?

【问题讨论】:

标签: javascript arrays iterator iterable


【解决方案1】:

我认为您缺少的是 iteratoriterable 之间存在差异。

数组是可迭代的,但不是迭代器。您可以从数组中获取迭代器,这就是它可迭代的原因:

// iterable
let arr = [1, 2, 3, 4]          

// Symbol.iterator function returns the iterator
let it = arr[Symbol.iterator]() 

// iterators have next()
console.log(it.next())          
console.log(it.next())          
console.log(it.next())          
console.log(it.next())          
console.log(it.next())

【讨论】:

  • 太棒了。这说明了。你能评论一下那个奇怪的下标语法吗? arr[Symbol.iterator]()?为什么我们将 Symbol.iterator 放在方括号内?
  • @TomAuger -- Symbol.iteratorSymbol。括号表示法只是使用 Symbol.iterator 返回的键对返回函数的数组进行属性查找。这允许保证密钥是唯一的。不像字符串array["Iterator"] 这样您可能会意外覆盖。 JS 内置了一些“知名符号”——当然,您也可以创建自己的。
  • 发了一个后续问题来加深我对这个特定实现原因的理解:stackoverflow.com/questions/56258471/…
  • 澄清:JavaScript 中的Array 是一个Iterable,它返回一个IterableIterator,然后支持递归解析。示例:[1,2,3][Symbol.iterator]()[Symbol.iterator]()[Symbol.iterator]()
【解决方案2】:

Mark Meyer 的回答帮助您了解 iterableiterator 之间的关键区别。

如果你想让你自己的值可迭代,你必须实现Symbol.iterator -

class Squares {
  constructor (...values) {
    this.values = values
  }
  *[ Symbol.iterator ] () {
    for (const v of this.values)
      yield v * v
  }
}

const iterable =
  new Squares(1, 2, 3, 4, 5)

for (const v of iterable)
  console.log(v)
// 1
// 4
// 9
// 16
// 25

console.log(Array.from(iterable))
// [ 1, 4, 9, 16, 25 ]

现在看看我们如何从可迭代对象中获取迭代器 -

class Squares {
  constructor (...values) {
    this.values = values
  }
  *[ Symbol.iterator ] () {
    for (const v of this.values)
      yield v * v
  }
}

const iterable =
  new Squares(1, 2, 3, 4, 5)

const iterator =
  iterable[Symbol.iterator]()

console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 4, done: false }
console.log(iterator.next()) // { value: 9, done: false }
console.log(iterator.next()) // { value: 16, done: false }
console.log(iterator.next()) // { value: 25, done: false }
console.log(iterator.next()) // { value: undefined, done: true }

【讨论】:

  • 代替上面的*[Symbol.iterator](){,是否可以创建一个更常规命名的方法,例如*getIterator(){?还是有一些与Symbol.iterator 相关的幕后“魔法”让它在幕后工作?
  • 您可以将方法命名为getIterator,但按惯例使用Symbol.iterator 是为了利用其他JavaScript 功能,如Array.fromfor-of 语法等。有关详细信息,请参阅Symbol.iterator 上的文档。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
相关资源
最近更新 更多