Skip to content

Latest commit

 

History

History
135 lines (96 loc) · 3.12 KB

10.md

File metadata and controls

135 lines (96 loc) · 3.12 KB

十、迭代器

迭代器是可以遍历集合的对象。它们支持像。NET CLR IEnumerable或 Java Iterable对象。他们可以用for..offor..in推广到基于自定义迭代器的迭代。它们也不需要实现数组,因此支持像 LINQ 这样的懒惰设计模式。

下面是一个产生斐波那契数的迭代器定义的例子:

代码清单 137

  let fibonacci = {
    [Symbol.iterator]() {
      let
  pre = 0,
  cur = 1;
      return
  {
        next() {
          [pre, cur] = [cur, pre +
  cur];
          return
  { done: false,
  value: cur }
        }
      }
    }
  }

首先要注意的是Symbol.iterator的用法。定义迭代器时,这个关键字是必需的。基于该接口,您会注意到迭代器返回一个函数next。有趣的是,在next函数内部,我们看到了破坏的例子。这比在多个语句中编写等价语句更方便。最后,我们看到next函数返回一个具有两个属性的对象文字。

让我们转到下一节,看看这个迭代器是如何使用的。

现在我们已经定义了一个迭代器,让我们看看如何使用它。考虑下面的代码示例:

代码清单 138

  for (var n of fibonacci) {
    //
  truncate the sequence at 100
    if
  (n > 100)
      break;
    console.log(n);
  }

可以看到for..of的语法和for..in是一样的。我们缩短了序列,这样我们就可以显示输出,而不用填满整个页面。以下是我们执行上述代码时的输出:

代码清单 139

  1
  2
  3
  5
  8
  13
  21
  34
  55
  89

让我们看另一个使用带数组的for..of的例子:

代码清单 140

  for (let element of [1,
  2, 3])
  {
    console.log(element);
  }

前面的代码也可以编写如下:

代码清单 141

  let elements = [1, 2, 3];
  for (let element of elements) {
    console.log(element);
  }

以下是前面代码的输出:

代码清单 142

  1
  2
  3

当我们比较for..offor..in时,我们会看到for..in迭代属性名而for..of迭代属性值。

让我们通过查看String的内置 iterable 来进一步了解迭代器。考虑以下代码:

代码清单 143

  let someString = "hi";
  var iterator = someString[Symbol.iterator]();
  console.log(iterator + "");

  console.log(iterator.next());
  console.log(iterator.next());
  console.log(iterator.next());

这里,我们正在创建一个字符串变量someString,它包含字符串hi。接下来,我们使用Symbol.iterator语法从someString变量创建一个迭代器。最后,我们注销迭代器。我们通过连接一个空字符串来强迫它使用toString函数。iterator.next()的调用序列向我们展示了返回的对象文字中包含的内容。

以下是前面代码的输出:

代码清单 144

  [object String Iterator]
  { value: 'h', done: false }
  { value: 'i', done: false }
  { value: undefined, done: true }

如您所见,这与我们在自定义斐波那契迭代器中实现的签名相同。希望这能让你更好地理解迭代器是如何工作的。