ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript の反復可能なオブジェクトとイテレータをご存知ですか?

JavaScript の反復可能なオブジェクトとイテレータをご存知ですか?

醉折花枝作酒筹
醉折花枝作酒筹転載
2021-08-09 17:53:542659ブラウズ

反復はコレクション要素にアクセスするメソッドです。反復可能なオブジェクトは反復可能オブジェクトと呼ばれます。反復子は、走査位置を記憶できるオブジェクトです。反復子オブジェクトは、コレクションの最初の要素からすべての要素が終了するまでアクセスを開始します。にアクセスされた場合、イテレータは前方にのみ移動でき、後方には移動できません。

遅延評価

遅延評価は、「遅延計算」または「遅延計算」と訳されることが多く、実際に実行する必要がある場合にのみ式の値を計算することを指します。

遅延評価の反対は早期評価です。早期評価は貪欲評価または厳密評価とも呼ばれ、ほとんどの従来のプログラミング言語の評価戦略です。

遅延評価の特性を最大限に活用する利点は、主に次の 2 つの側面に反映されます。
  • 不要な計算を回避し、パフォーマンスを向上させます。
  • スペースを節約し、無限ループのデータ構造を可能にします。

イテレータ

ES6 のイテレータを使用すると、ユーザー定義のデータ シーケンスを遅延評価して作成できます。反復はデータを走査するためのメカニズムです。イテレータは、データ構造 (Iterable と呼ばれる) の要素をトラバースするために使用されるポインタであり、一連の値を生成するために使用されるポインタです。

イテレータは、反復可能なオブジェクトです。データ コンテナを抽象化し、反復可能なオブジェクトのように動作します。

イテレータはインスタンス化時に各項目の値を計算せず、要求されたときにのみ次の値を生成します。これは、特に大規模なデータ セットや無限要素のシーケンスの場合に非常に便利です。

反復可能オブジェクト

反復可能オブジェクトは、その要素をパブリックにアクセスできるようにするデータ構造です。 JS の多くのオブジェクトは反復可能です。検出するのは簡単ではないかもしれませんが、注意深く調べると反復の特徴がわかります:
  • new Map([iterable])
  • new WeakMap([iterable])
  • new Set([iterable])
  • new WeakSet ([反復可能])
  • ##Promise.all([反復可能])

  • ##Promise.race([反復可能])

  • Array.from([iterable])

反復可能なオブジェクトも必要です。そうでない場合は、型エラーがスローされます。例:

  • for ... of

  • ... (展開演算子)

    const [a, b, ..] = iterable (代入の構造化)

  • yield* (ジェネレーター)

JavaScript には、組み込みの反復可能な項目が多数あります:

String、Array、TypedArray、Map 、セット。

反復プロトコル

反復子と反復可能オブジェクトは反復プロトコルに従います。

プロトコルは一連のインターフェイスであり、その使用方法を指定します。
イテレータはイテレータ プロトコルに従い、イテラブルはイテラブル プロトコルに従います。

反復可能プロトコル

オブジェクトを反復可能にするには、反復子のファクトリである Symbol.iterator を通じて反復子メソッドを実装する必要があります。

TypeScript を使用すると、反復可能なプロトコルは次のようになります。

interface Iterable {
  [Symbol.iterator]() : Iterator;
}

Symbol.iterator]() はパラメーターのない関数です。反復可能オブジェクトでそれを呼び出すということは、これを通じて反復可能オブジェクトにアクセスできることを意味します。これは、通常の関数またはジェネレーター関数にすることができます。

イテレータ プロトコル

イテレータ プロトコルは、一連の値を生成する標準的な方法を定義します。

オブジェクトがイテレータになるためには、next() メソッドを実装する必要があります。イテレータは return() メソッドを実装できます。これについては、この記事で後ほど説明します。

TypeScript を使用すると、イテレータ プロトコルは次のようになります。

interface Iterator {
    next() : IteratorResult;
    return?(value?: any): IteratorResult;
}

IteratorResult は次のように定義されます。

interface IteratorResult {
    value?: any;
    done: boolean;
}

  • done は、イテレータが使用済み、false はまだ生成される値があることを意味し、true はイテレータが終了したことを意味します。

  • value には任意の JS 値を指定できます。これはコンシューマに表示される値です。

done が true の場合、値は省略できます。

構成

イテレータと反復可能オブジェクトは、次の図で表すことができます:

JavaScript の反復可能なオブジェクトとイテレータをご存知ですか?

## 基本的な知識は次のとおりです。次に、いくつかの例を用いてイメージを深めていきましょう。

Range Iterator

非常に基本的なイテレータである createRangeIterator イテレータから始めます。

手動で it.next() を呼び出して、次の IteratorResult を取得します。最後の呼び出しは {done: true} を返します。これは、イテレーターが使用され、値を生成しなくなったことを意味します。

function createRangeIterator(from, to) {
  let i = from;

  return {
    next() {
      if (i <= to) {
        return { value: i++, done: false };
      } else {
        return { done: true };
      }
    }
  }
}

const it = createRangeIterator(1, 3);

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

JavaScript の反復可能なオブジェクトとイテレータをご存知ですか?

Iterable range iterator

この記事の前半で、JS の特定のステートメントには Iterable オブジェクトが必要であると述べました。したがって、前の例は for...of ループとともに使用すると機能しません。

しかし、反復子および反復可能プロトコルに準拠するオブジェクトを作成するのは非常に簡単です。

function createRangeIterator (from, to) {
  let i = from

  return {
    [Symbol.iterator] () {
      return this
    },
    next() {
      if (i <= to) {
        return { value: i++, done: false }
      } else {
        return { done: true }
      }
    }
  }
}

const it = createRangeIterator(1, 3)

for (const i of it) {
  console.log(i)
}

无限序列迭代器

迭代器可以表示无限制大小的序列,因为它们仅在需要时才计算值。

注意不要在无限迭代器上使用扩展运算符(...),JS 将尝试消费迭代器,由于迭代器是无限的,因此它将永远不会结束。 所以你的应用程序将崩溃,因为内存已被耗尽 

同样,for ... of 循环也是一样的情况,所以要确保能退出循环:

function createEvenNumbersIterator () {
  let value = 0

  return {
    [Symbol.iterator] () {
      return this
    },
    next () {
      value += 2
      return { value, done: false}
    }
  }
}

const it = createEvenNumbersIterator()

const [a, b, c] = it
console.log({a, b, c})

const [x, y, z] = it
console.log({ x, y, z })

for (const even of it) {
  console.log(even)
  if (even > 20) {
    break
  }
}

JavaScript の反復可能なオブジェクトとイテレータをご存知ですか?

关闭迭代器

前面我们提到过,迭代器可以有选择地使用return()方法。 当迭代器直到最后都没有迭代时使用此方法,并让迭代器进行清理。

for ... of循环可以通过以下方式更早地终止迭代:

  • break

  • continue

  • throw

  • return

function createCloseableIterator () {
  let idx = 0
  const data = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;]

  function cleanup() {
    console.log(&#39;Performing cleanup&#39;)
  }
  return {
    [Symbol.iterator]() { return this },
    next () {
      if (idx <= data.length - 1) {
        return { value: data[idx++], done: false }
      } else {
        cleanup()
        return { done: true }
      }
    },
    return () {
      cleanup()
      return { done: true }
    }
  }
}

const it = createCloseableIterator()

for (const value of it) {
  console.log(value)
  if (value === &#39;c&#39;) {
    break
  }
}

console.log(&#39;\n----------\n&#39;)

const _it = createCloseableIterator();
for (const value of _it) {
  console.log(value);
}

JavaScript の反復可能なオブジェクトとイテレータをご存知ですか?

  • 如果知道迭代器已经结束,则手动调用cleanup()函数。

  • 如果突然完成,则return()起作用并为我们进行清理。

【推荐学习:javascript高级教程

以上がJavaScript の反復可能なオブジェクトとイテレータをご存知ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。