js
1const iter = Array.from( new Array(10), (_,i)=>i )[Symbol.iterator](); // イテレータ(仮) 2let [x,y,z] = iter; 3if ( ! iter.next().done ){ 4 [x,y,z] = iter; 5} 6console.log(x,y,z); 7/* 84,5,6 9*/
頭書コードですが、イテレータが終了していなければ再度代入して値を取得する、というコードなのですが、終了しているかどうかを判定するために.next().done
としているため、値がひとつ進んでしまいます。
これを値を進めずに、イテレータが終了しているかどうか判別する方法はありますか?
(ECMAScriptの仕様候補にあれば、ブラウザ未実装の機能でも構いません。)
もちろん、
js
1let x = iter.next(); 2let y = iter.next(); 3let z = iter.next(); 4if ( ! z.done ){ 5 x = iter.next(); 6 y = iter.next(); 7 z = iter.next(); 8} 9x = x.value; 10y = y.value; 11z = z.value;
とすればいいのはわかりますが、分割代入もしたいのです。
配列にするのが手っ取り早いというのは理解していますので、純粋に「できるのかな?」という疑問であるとお読みいただければと。
よろしくお願いいたします。
解決されたコード
think49 さんのご回答で解決しました。
自前ではないイテレータで使いたかったので、ラッパ関数を作ってみました。
js
1const originalIter = Array.from( new Array(10), (_,i)=>i )[Symbol.iterator](); 2 3const iterWrapper = function(iter){ 4 let _done = false; 5 return { 6 next(){ 7 const _next = iter.next(); 8 _done = _next.done; 9 return _next; 10 }, 11 //_done:false, 12 done(){ 13 return _done; 14 }, 15 [Symbol.iterator](){ 16 return this; 17 } 18 } 19} 20 21const iter = iterWrapper(originalIter); 22 23let [x,y,z] = iter; 24if (!iter.done()){ 25 [x,y,z] = iter; 26} 27 28console.log(x,y,z); 29/* 303,4,5 31*/
また、補足欄でのご指摘も非情に示唆に富むものでした。
イテレータが iterable とは限らない、というのは目から鱗です。
自前でイテレータを実装する時は、
js
1 [Symbol.iterator](){ 2 return this; 3 }
が必須じゃないか、と思いました。

回答1件
あなたの回答
tips
プレビュー