2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

イテレータはイテラブルではないので分割代入できない

Posted at

要旨

  • イテレータは分割代入できない。
  • 分割代入できるのはイテラブル。
  • イテレータはイテラブルとは限らない。
  • 自前で実装したイテレータには、[Symbol.iterator](){return this;}を生やすこと。

コード

const fib = function fib(){
  let n_1 = 1, n_2 = 0;
  const iteratorResult ={
    value: n_1,
    done: false
  };
  return {
    next(){
      iteratorResult.value = n_1;
      [ n_1, n_2 ] = [ n_1 + n_2, n_1 ];
      return iteratorResult;
    }
  }
}

let f = fib();
let[a, b, c, d, e] = f;
/*
Exception: TypeError: f is not iterable
*/

問題

自前で実装した無限フィボナッチ数列イテレータですが、分割代入をしようとすると
TypeError: f is not iterable
と、イテラブルじゃないよ、と返ってきます。
もちろん、for ... of構文でも同様のエラーになります。
なぜか。

分割代入できるのはイテレータではなくてイテラブル

iterable (反復可能)プロトコルによって、JavaScript オブジェクトは、for..of構造で値がループしているもの等の反復動作を定義、または、カスタマイズできます。
(略)
iterable であるために、オブジェクトは@@iterator メソッドを実装する必要があります。
反復処理プロトコル - JavaScript | MDN

MDNを見れば明らかだったのですが、分割代入できるのはイテレータではなくてイテラブルであり、イテレータであっても @@iterator メソッドがなければイテラブルではない、ということです。

ジェネレータはどうなっているのか

const fib = function* fib( n_1 = 0, n_2 = 0 ){
  const n = n_1 + n_2 || 1;
  yield n;
  yield* fib( n, n_1 );
}

let f = fib();
f[Symbol.iterator]() === f;
/*
true
*/

なるほどね。

解決方法

const fib = function fib(){
  let n_1 = 1, n_2 = 0;
  const iteratorResult ={
    value: n_1,
    done: false
  };
  return {
    [Symbol.iterator](){ return this; },
    next(){
      iteratorResult.value = n_1;
      [ n_1, n_2 ] = [ n_1 + n_2, n_1 ];
      return iteratorResult;
    }
  }
}

let f = fib();
let[a, b, c, d, e] = f;
e;
/*
5
*/

ということで、自前実装のイテレータには、thisを返す[Symbol.iterator]メソッドを生やしておきましょう。
↓このMDNの説明は若干不親切かな、と思いました。
イテレーターとジェネレーター - JavaScript | MDN

これを教えてくれた人

@think49 さんです。感謝。
JavaScript - イテレータを進めずに終了しているかどうかを取得する方法はありますか?|teratail
 

2
1
4

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?