0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WebフロントエンドAdvent Calendar 2024

Day 19

スプレッド構文やfor/ofを支えるイテレータとはなにか?仕様からみてみよう

Last updated at Posted at 2024-12-21

はじめに

スプレッド構文...for/ofによって配列要素を1つずつ取得して変数に代入したり、処理したりすることができます。
for/ofなどによる繰り返し処理はどのようなオブジェクトに対しても行えるわけではなく、反復可能オブジェクトと呼ばれるオブジェクトに限られます。

反復可能オブジェクトとは、Symbol.iteratorメソッドを持つオブジェクトのことで、Symbol.iteratorメソッドはイテレータを返します。

この記事では反復処理を可能とする、イテレータの概要についてまとめてみたいと思います。

反復可能オブジェクト

反復可能オブジェクトは、Symbol.iteratorメソッドを持つオブジェクトのことです。
Symbol.iteratorメソッドはイテレータを返します。

組み込みの反復可能オブジェクトには、StringArrayMapSetなどがあります。
自作の反復可能オブジェクトを作成することも可能で、Symbol.iteratorメソッドやイテレータを自前で実装します。

Synbol.iteratorメソッドを定義して、「0から9までのランダムな数値」から9までを反復する、反復可能オブジェクトは次のように作ることができます。

const iterableObject = {
    [Symbol.iterator]() {
        const random = Math.floor(Math.random() * 10) // 0から9の整数値をランダムに生成
        let restNum = random
        return {
            next() {
                restNum++
                if (restNum < 10) {
                    return { done: false, value: restNum }
                } else {
                    return { done: true, value: undefined }
                }
            }
        }
    }
}

for(const num of iterableObject){
    console.log(num)
}

オブジェクトの中に[Symbol.iterator](){...}の形でメソッドを定義しています。
このメソッドが返しているオブジェクトがイテレータです。

イテレータ

イテレータとは、要素に順にアクセスするための仕組みのことで、JavaScript ではnext()メソッドを実装したオブジェクトのことをイテレータと呼びます。

next()メソッド

next()メソッドは、反復結果オブジェクト(IteratorResult)を返すメソッドです。

反復結果オブジェクトとは、donevalueプロパティを持つオブジェクトで、doneにはbooleanが、valueには任意の値1がはいります。

next()の仕様

ECMAScript 仕様書には、next()について次のように記載されています。

value
a function that returns an IteratorResult object

next()メソッドの返り値は反復結果オブジェクトであることが明記されていますね。

また、next()は以下の要件を満たす必要があることが記されています。

Requirement
The returned object must conform to the IteratorResult interface. If a previous call to the next method of an Iterator has returned an IteratorResult object whose "done" property is true, then all subsequent calls to the next method of that object should also return an IteratorResult object whose "done" property is true. However, this requirement is not enforced.

(拙訳)
nextメソッドから返されるオブジェクトは IteratorResultインターフェースに準拠すること。
イテレータが呼び出したnextメソッドが、donetrueの反復結果オブジェクトを返した場合、それ以降のnext()メソッドの呼び出しもすべて、donetrueの反復結果オブジェクトを返す必要がある。しかし、この要件は強制されない。

next()メソッドは反復結果オブジェクトを返すことが最低限の要件となっているわけですね。

doneプロパティ

doneについては、仕様では以下のような要件となっています。

Requirement
This is the result status of an iterator next method call. If the end of the iterator was reached "done" is true. If the end was not reached "done" is false and a value is available. If a "done" property (either own or inherited) does not exist, it is considered to have the value false.

doneはイテレータのnext()メソッドの結果を表すプロパティです。
イテレータが終端に達した時にtrueとなります。
イテレータが終端に達していない時はfalseとなり、値が利用可能です。
doneプロパティ(自身のプロパティまたは継承したプロパティ)がないときには、falseとして扱われます。

valueプロパティ

valueについては、仕様では以下のような要件となっています。

Requirement
If done is false, this is the current iteration element value. If done is true, this is the return value of the iterator, if it supplied one. If the iterator does not have a return value, "value" is undefined. In that case, the "value" property may be absent from the conforming object if it does not inherit an explicit "value" property.

valueは、donefalseのときには現在の反復要素の値をもちます。
donetrueのときにはイテレータに設定されている返り値となります。
イテレータが返り値をもたないときは、valueundefinedとなるか、明示的なvalueプロパティを継承していないならばvalueプロパティ自体が省略されることがあります。

ここで、先ほどの例でSynbol.iteratorが返していたオブジェクトをみてみます。

 {
    next() {
        restNum++
        if (restNum < 10) {
            return { done: false, value: restNum }
        } else {
            return { done: true, value: undefined }
        }
    }
}

next(){ done: false, value: restNum }{ done: true, value: undefined }という反復結果オブジェクトを返しており、donefalseのときにのみ値が設定されていることがわかります。
また、一度donetrueとなると、それ以降は処理が反復されたとしてもrestNum < 10を満たすことはなく、常にdonetrueを返すこともわかります。

確かにこのオブジェクトはイテレータの仕様要件を満たしていますね。

まとめ

複数の似た名前のオブジェクトが出てきたため、最後にまとめてみます。

  • 反復可能オブジェクト(Iterable Object)
    • Symbol.iteratorメソッドを持つオブジェクト
    • ArrayMapは組み込みの反復可能オブジェクト
  • イテレータ(Iterator)
    • next()メソッドを持つオブジェクト
    • Symbol.iteratorメソッドはイテレータを返す
  • 反復結果オブジェクト(Iterator Reslut Object)
    • イテレータのnext()メソッドから返されるオブジェクト
    • donevalueプロパティをもつ
  1. 任意の値とは、仕様ではECMAScript Language Typesと呼ばれる値です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?