JavaScript supports looping through data set objects such as arrays using control structures such as for…of and the spread operator .... これはイテラブルと呼ばれ、この機能をサポートするデータ構造はイテラブルと呼ばれます。 While JavaScript provides maps, arrays and sets with an iterable property by default, regular JavaScript objects do not have this by default.

Iterableは、他のデータコンシューマーがその要素に順次アクセスできるようにするメカニズムを提供するデータ構造です。 データを1つずつアンロードする自己パッケージ化されたデータ構造を想像してみてください。 for...of ループ。

The concept of the iterable protocol can be split into the iterable, the data structure itself, and the iterator, a pointer that moves over the iterable. Consider an array for example. When the array is used in a for...of ループ、iterableプロパティが呼び出され、 iterator. この反復可能なプロパティは、次のように名前空間が付けられます。 Symbol.iterator そして、それが返すオブジェクトは、すべてのループ制御構造によって共有される共通のインターフェースで使用できます。

ある意味で、 Symbol.iterator can be compared to an iterator factory that produces an iterator whenever the data structure is placed in a loop.

イテレータがデータ構造上を移動し、要素を順番に提供すると、イテレータによって返されるオブジェクトには、 valuedone 財産。

値は、イテレータが指す現在のデータ値を示し、 done は、イテレータがデータ構造の最後の要素に到達したかどうかを示すブール値です。

これ {value, done} ループなどの構造によって消費されます。 In order for the iterator method to call the next object, a next() Symbol.iterator()メソッド内で定義されたメソッド。

In other words, the iterator property can be defined as a property that knows how to access elements from a collection one by one. It also contains the logic to stop, such as when there are no more elements in an array.

Understanding Objects and Iterables

JavaScript objects don’t come with iterables by default. Here are some potential rationales::

  • オブジェクトの重要な機能の1つは、ユーザー定義であるということです。 だから静かに滑り込む [Symbol.iterator]() into the object could result in unexpected behavior.
  • The previous point also means that it can be added manually by the user, considering that all object compositions might not be similar. So having a common iterable property can be meaningless.
  • If you want to loop over the top level elements in the object, you can use a for...in ループ。
  • Mapsオブジェクトタイプの使用がより適切な場合があります。

If you still need an iterable, a simple iterable implementation on objects would look like this:

let Reptiles = {
  biomes: {
    water: ["Alligators", "Crocs"],
    land: ["Snakes", "Turtles"]
  },

  [Symbol.iterator]() {
    let reptilesByBiome = Object.values(this.biomes);
    let reptileIndex = 0;
    let biomeIndex = 0;
    return {
      next() {
        if (reptileIndex >= reptilesByBiome[biomeIndex].length) {
          biomeIndex++;
          reptileIndex = 0;
        }

        if (biomeIndex >= reptilesByBiome.length) {
          return { value: undefined, done: true };
        }

        return {
          value: reptilesByBiome[biomeIndex][reptileIndex++],
          done: false
        };
      }
    };
  }
};

// now iterate over the new `Reptiles` iterable:
for (let reptile of Reptiles) console.log(reptile);

出力は次のようになります。

Alligators
Crocs
Snakes
Turtles

With this example, you can see iterators can be implemented within the object. Iterablesは、特定の状況を処理しながら使いやすくし、長いパス名を記述しないようにするオブジェクトの強力なプロパティになります。

イテレータにアクセスする

のようなループ for...of まで反復可能物を消費する組み込みのメカニズムを持っている done 値はtrueと評価されます。 If you want to consume the iterable on your own though, without a built-in loop, you can get the iterator from the iterable and then call next() on it manually.

Given the same example as above, you could get an iterator from Reptiles そのを呼び出すことによって Symbol.iterator このような:

let reptileIterator = Reptiles[Symbol.iterator]();

次に、次のようにイテレータを使用できます。

console.log(reptileIterator.next());
// {value: "Alligators", done: false}
console.log(reptileIterator.next());
// {value: "Crocs", done: false}
console.log(reptileIterator.next());
// {value: "Snakes", done: false}
console.log(reptileIterator.next());
// {value: "Turtles", done: false}
console.log(reptileIterator.next());
// {value: undefined, done: true}

console.log(reptileIterator.next());
// TypeError: Cannot read property 'length' of undefined

ご覧のとおり、イテレータには next() iterableの次の値を返すメソッド。 の値 done にのみ評価します true 次々と next() 最後の値が返されたら呼び出します。したがって、イテレータ全体を調べるには、常にもう1つの呼び出しがあります。 next() イテレータにデータがあるよりも。 呼び出し next() イテレータがイテレータの最後に達した後も、次のようになります。 TypeError 投げられる。

Conclusion

With this tutorial, you have gone through the different parts and mechanisms behind looping through a data set with JavaScript. You’ve gone through the reasons JavaScript objects do not come with this ability to iterate innately, and demonstrated the option to manually implement your own iterables.