ES6のJavaScriptイテレーターの概要

EcmaScript 2015(ES6としても知られています)には、言語レベルでシーケンス(制限付きなど)を定義できる完全に新しいイテレーターの概念が導入されています。



これについて詳しく説明しましょう。 私たちはすべてforループ演算子に精通しており、多くの人があまり人気のないfor-in兄弟を知っています。 後者は、イテレータを使用する基本的な原則を説明するために使用できます。

for (var key in table) { console.log(key + ' = ' + table[key]); }
      
      





for-inループ演算子には多くの問題がありますが、おそらく最大の問題は、一貫性の保証がないことです。 イテレータを使用してこの問題を解決してみましょう。 詳細はこちら!



For-ofサイクル


for-ofは、イテレーターで動作するように設計された、ES6で導入された新しい構文です。

 for (var key of table) { console.log(key + ' = ' + table[key]); }
      
      





この例では、キーシーケンスを保証するイテレータアプリケーションが必要です。 オブジェクトを反復可能にするには、反復可能なプロトコルを使用する必要があります。つまり、オブジェクト(またはプロトタイプチェーンの上位のオブジェクトの1つ)にSymbol.iteratorキーを持つプロパティが必要です。 これがfor-ofを使用するものであり、この特定の例ではテーブル[Symbol.iterator]になります。



Symbol.iteratorは、ES6の別のアドオンであり、詳細については後で説明します。 今のところ、通常のオブジェクトキーと競合しない特別なキーを指定する方法としてSymbol.iteratorを検討してください。



テーブル[Symbol.iterator]オブジェクトの要素は、イテレータプロトコルに準拠する関数である必要があります。つまり、次のようにオブジェクトを返す必要があります:{next:function(){}}。

 table[Symbol.iterator] = function () { return { next: function () {} } }
      
      





次の関数がfor-ofで呼び出されるたびに、{value:...、done:[true / false]}のようなオブジェクトを返す必要があります。 イテレータの完全な実装は次のとおりです。

 table[Symbol.iterator] = function () { var keys = Object.keys(this).sort(); var index = 0; return { next: function () { return { value: keys[index], done: index++ >= keys.length }; } } }
      
      





怠azine


イテレータにより、nextの最初の呼び出しまで関数の実行を遅らせることができます。 上記の例では、反復子を呼び出すとすぐに、キーの取得とソートのプロセスが開始されます。 ただし、nextが呼び出されない場合はどうなりますか? 時間を無駄にしているだけです。 それでは、コードを最適化しましょう。

 table[Symbol.iterator] = function () { var _this = this; var keys = null; var index = 0; return { next: function () { if (keys === null) { keys = Object.keys(_this).sort(); } return { value: keys[index], done: index++ >= keys.length }; } } }
      
      





for-ofとfor-inの違い


for-ofとfor-inの違いを理解することが重要です。 これがなぜそうなのかを示す簡単な例です。

 var list = [3, 5, 7]; list.foo = 'bar'; for (var key in list) { console.log(key); // 0, 1, 2, foo } for (var value of list) { console.log(value); // 3, 5, 7 }
      
      





ご覧のとおり、for-ofは配列内の値のみを返し、他のすべてのプロパティを省略します。 これは、配列反復子が予期されるパラメーターのみを返すためです。



組み込みのイテレーター


StringArrayTypedArrayMapSetには組み込みの反復子が含まれています。これらのプロトタイプオブジェクトにはSymbol.iteratorメソッドが含まれているためです。

 var string = "hello"; for (var chr of string) { console.log(chr); // h, e, l, l, o }
      
      





スプレッドを構築


Spreadステートメントは反復子も受け入れることができます。 これは次のようなものを使用できます。

 var hello = 'world'; var [first, second, ...rest] = [...hello]; console.log(first, second, rest); // wo ["r","l","d"]
      
      





無限反復子


無限のイテレータを使用することは、決してdoneを返さないのと同じくらい簡単です:true。 もちろん、無限ループが形成されていないことを確認する必要があります。

 var ids = { *[Symbol.iterator]: function () { var index = 0; return { next: function () { return { value: 'id-' + index++, done: false }; } }; } }; var counter = 0; for (var value of ids) { console.log(value); if (counter++ > 1000) { // let's make sure we get out! break; } }
      
      





発電機


ES6ジェネレーターに慣れていない場合は、 ドキュメントを読んでください。 一言で言えば、ジェネレーターは一時停止してから再開できる関数です。 最近、ジェネレーターはES6の機能について最も話題になっています。 コンテキストは再起動間で維持されます。 ジェネレータには、イテラブルとイテレータの両方のプロトコルが含まれています。 簡単な例を見てみましょう:

 function* list(value) { for (var item of value) { yield item; } } for (var value of list([1, 2, 3])) { console.log(value); } var iterator = list([1, 2, 3]); console.log(typeof iterator.next); // function console.log(typeof iterator[Symbol.iterator]); // function console.log(iterator.next().value); // 1 for (var value of iterator) { console.log(value); // 2, 3 }
      
      





上記のコードを考えると、ジェネレーターを使用してキーをソートするイテレーターのコードを書き換えることができます。

 table[Symbol.iterator] = function* () { var keys = Object.keys(this).sort(); for (var item of keys) { yield item; } }
      
      





まとめ


イテレータは、ループ、ジェネレータ、および変数のセットを操作することでまったく新しい次元を開きます。 それらは転送でき、クラスがパラメータのリストを記述するように設定し、「遅延」または無限リストを作成できます。 など



ES6今日


今日、ES6をどのように活用できますか? トランスパイラーの使用は、ここ数年で標準になりました。 単純な開発者も大企業も、それらを使用することに恥ずかしくない。 BabelはES6からES5へのトランスポーターであり、ES6のすべての革新をサポートします。



Browserifyを使用する場合はわずか数分で Babelを追加できます。 もちろん、Node.jsを使用したほとんどすべてのビルドがサポートされています。 例:Gulp、Grunt、その他多数。



ブラウザはどうですか?


ほとんどのブラウザは徐々に新しい機能を追加していますが 、まだ誰も完全にサポートしていません。 何、今待って? 状況によります。 1、2年後には一般的になる言語機能を使い始めるのは理にかなっています。 これにより、新しいステージに快適に移動できます。 ただし、ソースコードを完全に制御する必要がある場合は、ES5を待って使用することをお勧めします。



翻訳者: greebn9k (セルゲイ・グリブニャック)、 silmarilion (アンドレイ・ハカレフ)



All Articles