Skip to content

Instantly share code, notes, and snippets.

@pentamania
Last active December 14, 2019 09:10
Show Gist options
  • Save pentamania/b5b8bd8a08195a77e78c3da52a9c1b59 to your computer and use it in GitHub Desktop.
Save pentamania/b5b8bd8a08195a77e78c3da52a9c1b59 to your computer and use it in GitHub Desktop.
javascript generatorメモ

要訳

  • generator関数(*function)を実行するとgeneratorオブジェクト(以下genobj)を返す
  • json(配列)を使った応用ではyield*とfor-ofを使う

まずはgenerator関数の定義

// genobjを返す
var hoge = function*() {
  console.log('run hoge');
  yield "val of hoge"
}
var foo = function*() {
  console.log('run foo');
  yield "val of foo"
}

メインルーチン

普通

yield* でitertableなオブジェクト(genobjやarray)を渡すと、それがdoneになるまでイテレートする https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield*

var gen = (function*() {
  yield* hoge();
  yield* foo();
}());
for (let val of gen) {
  console.log(val); // run hoge, "val of hoge", run foo, "val of foo"
}

配列を使った応用

上では例えばjsonで渡されたデータを元にルーチンを実行すると言ったことができない。
しかしfor-ofを使えば可能

var jsonData = ["hoge", "hoge", "foo"]

// jsonDataを元にgenObjオンリーの配列をつくる
// 要はtasks = [window.hoge(), window.hoge(), window.foo()]と同じことをする
var tasks = jsonData.map((item)=> {
  return window[item]();
})

// メインルーチン作成
var gen = (function*() {
  for (let g of tasks) yield* g;
}());

// 以下は一緒
for (let val of gen) {
  console.log(val);
}

ちなみにforeachは使えない
コールバックではyieldは呼べないため(async/awaitの関係に似ている)

// Doesn't work
var gen = (function*() {
  tasks.forEach(function(g) {
    yield* g; // エラー
  });
}());

参考

https://sbfl.net/blog/2016/08/17/javascript-iterator-generator/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment