2016-03-30 5 views
1

私はthis article about javascript generatorsを読んでいた、と私は、次のスニペットに達し:このイテレータが次の値を返すのはなぜですか?

function *foo(x) { 
    var y = 2 * (yield (x + 1)); 
    var z = yield (y/3); 
    return (x + y + z); 
} 

var it = foo(5); 

// note: not sending anything into `next()` here 
console.log(it.next());  // { value:6, done:false } 
console.log(it.next(12)); // { value:8, done:false } 
console.log(it.next(13)); // { value:42, done:true } 

は、私が最初にit.next()の目的を理解していません。この行を実行した後、イテレータをvar z = yield (y/3)で一時停止し、yの値が6であるはずはありません。 it.next(12)yield (y/3)のパラメータを供給し、その後zを4にする必要はありませんか?私はなぜ機能の結果が5 + 12 + 4ではないのか分かりません。どういうわけか、最初のit.next()が無視されているかのようです。これは本当ですか?誰かが光を放つことができますか?

答えて

1

あなたは何が起こっているかを確認するためにいくつかのログ・ステートメントを追加したい場合があります:foo(5)を呼び出す

it {next: …} 
starting 
{ value:6, done:false } 
y 24 
{ value:8, done:false } 
z 13 
{ value:42, done:true } 

あなたが見ることができるように

function *foo(x) { 
    console.log("starting"); 
    var y = 2 * (yield (x + 1)); 
    console.log("y", y); 
    var z = yield (y/3); 
    console.log("z", z); 
    return (x + y + z); 
} 

var it = foo(5); 
console.log("it", it); 
console.log(it.next()); 
console.log(it.next(12)); 
console.log(it.next(13)); 

ログは、のみジェネレータオブジェクトを作成するのではなく、まだ始める。 it.next()への最初の呼び出しだけがそれを行い、最初のyieldから結果を返します。とにかくジェネレータ関数内ではアクセスできないため、この最初の呼び出しは引数をとりません。

.next(12)にのみ2回目の呼び出しは、ここで値を渡し、その渡された値が(その後2乗算される)yield式の結果であると、生成コードを再開します。

+0

が、私はこれを正しく理解して助けて?基本的には、最初の 'it.next()'を呼び出した後、6が呼び出し側に返され、ノードは同じ収量で関数をサスペンドしていますか?したがって、 'it.next(12)'を呼び出すとき、x + 1ではなく12を使用します。 – Geo

+0

@Geo:まさに 'yield'の仕組みですね:-)ほとんどの場合(イテレータのような)、渡さ​​れる値は気にしません(あるいは値がまったく渡されない)が、できるこれでいくつかの素晴らしいこと。あなたの質問にリンクしている記事シリーズを読んでください! – Bergi

2

これは

function *foo(x) { 
    var y = 2 * (yield (x + 1)); 
     // x = 5 (from foo(5)) so it yields 6 
     // next(12) => var y = 2 * (12) == 24 
    var z = yield (y/3); 
     // from above y = 24 so yields 8 
     // next(13) => var z = 13  
    return (x + y + z); 
     // 5 + 24 + 13 == 42 (and done: true) 
} 
関連する問題