From 511448890605c22a4e5381c0c2d8df4453b34fb9 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Tue, 1 Feb 2022 02:15:22 +0900 Subject: 2021/07/21 時点の英語版に同期 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/iteration_protocols/index.md | 347 ++++++++++----------- 1 file changed, 169 insertions(+), 178 deletions(-) (limited to 'files/ja/web/javascript/reference/iteration_protocols') diff --git a/files/ja/web/javascript/reference/iteration_protocols/index.md b/files/ja/web/javascript/reference/iteration_protocols/index.md index 0ea6bd0831..eb7117c8c7 100644 --- a/files/ja/web/javascript/reference/iteration_protocols/index.md +++ b/files/ja/web/javascript/reference/iteration_protocols/index.md @@ -3,130 +3,130 @@ title: 反復処理プロトコル slug: Web/JavaScript/Reference/Iteration_protocols tags: - ECMAScript 2015 - - Intermediate - - Iterable - - Iterator - - JavaScript - ガイド - - プロトコル - 中級者 - - 反復処理 + - 反復可能 - 反復子 + - JavaScript + - プロトコル translation_of: Web/JavaScript/Reference/Iteration_protocols --- -
{{jsSidebar("More")}}
+{{jsSidebar("More")}} -

ECMAScript 2015 で追加されたいくつかの機能の中で、反復処理プロトコルは新しい組み込みオブジェクトや構文ではなくプロトコルです。これらのプロトコルは以下のような単純な約束事によって、すべてのオブジェクトで実装することができます。

+ECMAScript 2015 で追加されたいくつかの機能の中で、**反復処理プロトコル**は新しい組み込みオブジェクトや構文ではなく**プロトコル**です。これらのプロトコルは以下のような単純な約束事によって、すべてのオブジェクトで実装することができます。 -

プロトコルは2つあります。 反復可能プロトコル反復子プロトコルです。

+プロトコルは 2 つあります。[反復可能プロトコル](#反復可能_iterable_プロトコル)と[反復子プロトコル](#反復子_iterator_プロトコル)です。 -

反復可能 (iterable) プロトコル

+## 反復可能 (iterable) プロトコル -

反復可能プロトコルによって、 JavaScript のオブジェクトは反復動作を定義またはカスタマイズすることができます。例えば、 {{jsxref("Statements/for...of", "for...of")}} 構造の中でどの値がループに使われるかです。一部の組み込み型は既定の反復動作を持つ組み込み反復可能オブジェクトで、これには {{jsxref("Array")}} や {{jsxref("Map")}} がありますが、他の型 ({{jsxref("Object")}} など) はそうではありません。

+**反復可能プロトコル**によって、 JavaScript のオブジェクトは反復動作を定義またはカスタマイズすることができます。例えば、 {{jsxref("Statements/for...of", "for...of")}} 構造の中でどの値がループに使われるかです。一部の組み込み型は既定の反復動作を持つ[組み込み反復可能オブジェクト](#組み込み反復可能オブジェクト)で、これには {{jsxref("Array")}} や {{jsxref("Map")}} がありますが、他の型 ({{jsxref("Object")}} など) はそうではありません。 -

反復可能であるために、オブジェクトは @@iterator メソッドを実装する必要があります。これはつまり、オブジェクト (または、プロトタイプチェーン上のオブジェクトの一つ) が {{jsxref("Symbol.iterator")}} 定数にて利用できる @@iterator キーのプロパティを持つ必要があります。

+**反復可能**であるために、オブジェクトは **`@@iterator`** メソッドを実装する必要があります。これはつまり、オブジェクト(または、[プロトタイプチェーン](/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)上のオブジェクトの一つ)が {{jsxref("Symbol.iterator")}} 定数にて利用できる `@@iterator` キーのプロパティを持つ必要があります。 - - - - - - - - - - - - - -
プロパティ
[Symbol.iterator]反復子プロトコルに準拠するオブジェクトを返す、引数なしの関数。
+| プロパティ | 値 | +| ------------------- | --------------------------------------------------------------------------------------------------------------- | +| `[Symbol.iterator]` | [反復子プロトコル](#反復子_iterator_プロトコル)に準拠するオブジェクトを返す、引数なしの関数。 | -

({{jsxref("Statements/for...of", "for...of")}} ループの始まりのように) オブジェクトが反復される必要があるときはいつでも、その @@iterator メソッドが引数なしで呼ばれます。そして、返される反復子は、反復される値を取得するために使用されます。

+({{jsxref("Statements/for...of", "for...of")}} ループの始まりのように) オブジェクトが反復される必要があるときはいつでも、その `@@iterator` メソッドが引数なしで呼ばれます。そして、返される**反復子**は、反復される値を取得するために使用されます。 -

なお、この引数なしの関数が呼び出されると、反復可能オブジェクト上のメソッドとして呼び出されます。従って関数の中では、 this キーワードを反復可能オブジェクトのプロパティにアクセスするために使用して、反復の間に何を提供するかを決めることができます。

+なお、この引数なしの関数が呼び出されると、反復可能オブジェクト上のメソッドとして呼び出されます。従って関数の中では、 `this` キーワードを反復可能オブジェクトのプロパティにアクセスするために使用して、反復の間に何を提供するかを決めることができます。 -

この関数は普通の関数、またはジェネレーター関数にすることができ、そのため呼び出されると、反復子オブジェクトが返されます。このジェネレーター関数の中では yield を使用してそれぞれの項目を提供することができます。

+この関数は普通の関数、またはジェネレーター関数にすることができ、そのため呼び出されると、反復子オブジェクトが返されます。このジェネレーター関数の中では `yield` を使用してそれぞれの項目を提供することができます。 -

反復子 (iterator) プロトコル

+## 反復子 (iterator) プロトコル -

反復子プロトコルは、値のシーケンス (有限でも無限でも) を生成するための標準的な方法と、すべての値が生成された場合の返値を定義します。

+**反復子プロトコル**は、値の並び(有限でも無限でも)を生成するための標準的な方法と、すべての値が生成された場合の返値を定義します。 -

以下の意味で next() メソッドを実装していれば、オブジェクトは反復子になります。

+以下の意味で **`next()`** メソッドを実装していれば、オブジェクトは反復子になります。 - - - - - - - - - - - - + + + + + + + + + + + +
プロパティ
next() -

引数なしの関数で、少なくとも以下の二つのプロパティを持つオブジェクトを返します。

- -
-
done (boolean)
-
-

反復子がシーケンス内の次の値を生成できるとき false の値になります。 (これは done プロパティが指定されていない場合も同じです。)

- -

反復子が反復シーケンスを終了した場合、 true の値になります。この場合、 value は任意で反復子の返値を指定します。

-
-
value
-
反復子によって返される任意の JavaScript 値。 donetrue のときは省略することができます。
-
- -

next() メソッドは常に donevalue などの適切なプロパティを持つオブジェクトを返します。オブジェクトでない値が返された場合 (例えば falseundefined)、 {{jsxref("TypeError")}} ("iterator.next() returned a non-object value") が発生します。

-
プロパティ
next() +

+ 引数が 0 個または 1 個の関数で、少なくとも以下の 2 つのプロパティを持つオブジェクトを返します。 next() メソッドが1つの引数で呼び出された場合、その引数は呼び出された next() メソッドで利用可能です。 +

+
+
done (boolean)
+
+

+ 反復子がシーケンス内の次の値を生成できるとき false の値になります。 (これは done プロパティが指定されていない場合も同じです。) +

+

+ 反復子が反復シーケンスを終了した場合、 true の値になります。この場合、 value は任意で反復子の返値を指定します。 +

+
+
value
+
+ 反復子によって返される任意の JavaScript 値。 donetrue のときは省略することができます。 +
+
+

+ next() メソッドは常に donevalue などの適切なプロパティを持つオブジェクトを返します。オブジェクトでない値が返された場合 (例えば falseundefined)、 {{jsxref("TypeError")}} ("iterator.next() returned a non-object value") が発生します。 +

+
-
-

メモ: 特定のオブジェクトが反復子プロトコルを実装しているかどうかを反射的に知ることはできません。しかし、反復子プロトコルと反復可能プロトコルの両方を満たすオブジェクトを作成するのは簡単です (以下の例にあるように)。

- -

そうすることで、反復可能オブジェクトを期待するさまざまな構文で反復子を使用できます。したがって、反復子プロトコルを実装するには反復可能プロトコルも実装しないと、ほとんど役に立ちません。

- -
// 反復子と反復可能の両プロトコルを満たす
-let myIterator = {
-    next: function() {
-        // ...
-    },
-    [Symbol.iterator]: function() { return this; }
-};
-
-
- -

例: 反復処理プロトコルの使用

- -

{{jsxref("String")}} は組み込み反復可能オブジェクトの一例です。

- -
let someString = 'hi';
+> **Note:** 特定のオブジェクトが反復子プロトコルを実装しているかどうかを反射的に知ることはできません。しかし、反復子プロトコルと反復可能プロトコルの**両方**を満たすオブジェクトを作成するのは簡単です(以下の例のように)。
+>
+>そうすることで、反復可能オブジェクトを期待するさまざまな構文で反復子を使用できます。したがって、反復子プロトコルを実装するには反復可能プロトコルも実装しないと、ほとんど役に立ちません。
+>
+> ```js
+> // 反復子と反復可能の両プロトコルを満たす
+> const myIterator = {
+>     next: function() {
+>         // ...
+>     },
+>     [Symbol.iterator]: function() { return this; }
+> };
+> ```
+>
+> しかし、可能であれば `iterable[Symbol.iterator]` は [`Set.prototype[@@iterator]()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Set/@@iterator) のように、常に先頭から始まる異なる反復子を返した方がよいでしょう。
+
+## 反復処理プロトコルの使用例
+
+{{jsxref("String")}} は組み込み反復可能オブジェクトの一例です。
+
+```js
+const someString = 'hi';
 console.log(typeof someString[Symbol.iterator]); // "function"
-
+``` -

String の{{jsxref("String/@@iterator", "既定の反復子", "", 1)}}は文字列のコードポイントを1つずつ返します。

+`String` の{{jsxref("String/@@iterator", "既定の反復子", "", 1)}}は文字列のコードポイントを 1 つずつ返します。 -
let iterator = someString[Symbol.iterator]();
+```js
+const iterator = someString[Symbol.iterator]();
 console.log(iterator + ''); // "[object String Iterator]"
 
 console.log(iterator.next()); // { value: "h", done: false }
 console.log(iterator.next()); // { value: "i", done: false }
-console.log(iterator.next()); // { value: undefined, done: true }
+console.log(iterator.next()); // { value: undefined, done: true } +``` -

一部の組み込みコンストラクター — 例えば{{jsxref("Operators/Spread_operator", "スプレッド構文", "", 1)}} — は、まったく同じ反復処理プロトコルを使用しています。

+一部の組み込みコンストラクター — 例えば{{jsxref("Operators/Spread_syntax", "スプレッド構文", "", 1)}} — は、まったく同じ反復処理プロトコルを使用しています。 -
console.log([...someString]); // ["h", "i"]
+```js +console.log([...someString]); // ["h", "i"] +``` -

自身の @@iterator を提供することによって反復動作を再定義できます。:

+自身の `@@iterator` を提供することによって反復動作を再定義できます。 -
// need to construct a String object explicitly to avoid auto-boxing
-let someString = new String('hi');
+```js
+// オートボックスを避けるために、明示的に String オブジェクトを構築する必要があります。
+const someString = new String('hi');
 
 someString[Symbol.iterator] = function () {
   return {
-    // this is the iterator object, returning a single element (the string "bye")
+    // これは反復子オブジェクトであり、単一の要素 (文字列 "bye") を返します。
     next: function () {
       return this._first ? {
         value: 'bye',
@@ -138,47 +138,48 @@ someString[Symbol.iterator] = function () {
     _first: true
   };
 };
-
+``` -

@@iterator を再定義することによって、反復処理プロトコルを使用する組み込みコンストラクターの動作にどれほど影響を与えるか注意してください。

+`@@iterator` を再定義することによって、反復処理プロトコルを使用する組み込みコンストラクターの動作にどれほど影響を与えるか注意してください。 -
console.log([...someString]); // ["bye"]
+```js
+console.log([...someString]); // ["bye"]
 console.log(someString + ''); // "hi"
-
+``` -

反復可能プロトコルの例

+## 反復可能プロトコルの例 -

組み込み反復可能オブジェクト

+### 組み込み反復可能オブジェクト -

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}}, {{jsxref("Set")}} は、すべての組み込み反復可能オブジェクトです。というのも、それらすべてのプロトタイプオブジェクトは @@iterator メソッドをもつからです。

+{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}}, {{jsxref("Set")}} は、すべての組み込み反復可能オブジェクトです。というのも、それらすべてのプロトタイプオブジェクトは `@@iterator` メソッドをもつからです。 -

ユーザー定義の反復可能オブジェクト

+### ユーザー定義の反復可能オブジェクト -

下記のように反復可能オブジェクトを生成できます。

+下記のように反復可能オブジェクトを生成できます。 -
let myIterable = {};
+```js
+const myIterable = {};
 myIterable[Symbol.iterator] = function* () {
     yield 1;
     yield 2;
     yield 3;
 };
 console.log([...myIterable]); // [1, 2, 3]
-
+``` -

反復可能オブジェクトを受け入れる組み込み API

+### 反復可能オブジェクトを受け入れる組み込み API -

反復可能オブジェクトを受け入れる API はたくさんあります。以下はその例です。

+反復可能オブジェクトを受け入れる API はたくさんあります。以下はその例です。 - +- {{jsxref("Map", "new Map([iterable])")}} +- {{jsxref("WeakMap", "new WeakMap([iterable])")}} +- {{jsxref("Set", "new Set([iterable])")}} +- {{jsxref("WeakSet", "new WeakSet([iterable])")}} -
new Map([[1, 'a'], [2, 'b'], [3, 'c']]).get(2); // "b"
+```js
+new Map([[1, 'a'], [2, 'b'], [3, 'c']]).get(2); // "b"
 
-let myObj = {};
+const myObj = {};
 
 new WeakMap([
     [{}, 'a'],
@@ -194,21 +195,20 @@ new WeakSet(function* () {
     yield myObj
     yield {}
 }()).has(myObj);           // true
-
+``` -

関連情報

+#### 関連情報 - +- {{jsxref("Promise.all()", "Promise.all(iterable)")}} +- {{jsxref("Promise.race()", "Promise.race(iterable)")}} +- {{jsxref("Array.from()", "Array.from(iterable)")}} -

反復可能オブジェクトを期待する構文

+### 反復可能オブジェクトを期待する構文 -

いくつかの文や式は反復可能オブジェクトを期待します。例えば、 {{jsxref("Statements/for...of", "for...of")}} ループ、{{jsxref("Operators/Spread_syntax", "スプレッド演算子", "", "1")}}、{{jsxref("Operators/yield*", "yield*")}}、{{jsxref("Operators/Destructuring_assignment", "分割代入", "", "1")}} などです。

+いくつかの文や式は反復可能オブジェクトを期待します。例えば、 {{jsxref("Statements/for...of", "for...of")}} ループ、{{jsxref("Operators/Spread_syntax", "スプレッド演算子", "", "1")}}、{{jsxref("Operators/yield*", "yield*")}}、{{jsxref("Operators/Destructuring_assignment", "分割代入", "", "1")}} などです。 -
for (let value of ['a', 'b', 'c']) {
+```js
+for (const value of ['a', 'b', 'c']) {
     console.log(value);
 }
 // "a"
@@ -225,29 +225,30 @@ console.log(gen().next()); // { value: "a", done: false }
 
 [a, b, c] = new Set(['a', 'b', 'c']);
 console.log(a);            // "a"
+```
 
-
+### 非正規形反復可能オブジェクト -

非整形反復可能オブジェクト

+反復可能オブジェクトの `@@iterator` メソッドが反復子オブジェクトを返さない場合、それは**非正規形**反復可能オブジェクトと見なされます。 -

反復可能オブジェクトの @@iterator メソッドが反復子オブジェクトを返さない場合、それは非整形反復可能オブジェクトと見なされます。

+これを使用すると、ランタイムエラーやバグの挙動をもたらす可能性があります。 -

これを使用すると、ランタイムエラーやバグの挙動をもたらす可能性があります。

+```js example-bad +const nonWellFormedIterable = {}; +nonWellFormedIterable[Symbol.iterator] = () => 1; +[...nonWellFormedIterable]; // TypeError: [] is not a function +``` -
let nonWellFormedIterable = {}
-nonWellFormedIterable[Symbol.iterator] = () => 1
-[...nonWellFormedIterable] // TypeError: [] is not a function
-
+## 反復子の例 -

反復子の例

+### 簡単な反復子 -

簡単な反復子

- -
function makeIterator(array) {
+```js
+function makeIterator(array) {
   let nextIndex = 0
   return {
     next: function() {
-      return nextIndex < array.length ? {
+      return nextIndex < array.length ? {
         value: array[nextIndex++],
         done: false
       } : {
@@ -257,16 +258,17 @@ nonWellFormedIterable[Symbol.iterator] = () => 1
   };
 }
 
-let it = makeIterator(['yo', 'ya']);
+const it = makeIterator(['yo', 'ya']);
 
 console.log(it.next().value); // 'yo'
 console.log(it.next().value); // 'ya'
 console.log(it.next().done);  // true
-
+``` -

無限の反復子

+### 無限の反復子 -
function idMaker() {
+```js
+function idMaker() {
   let index = 0;
   return {
     next: function() {
@@ -278,24 +280,25 @@ console.log(it.next().done);  // true
   };
 }
 
-let it = idMaker();
+const it = idMaker();
 
 console.log(it.next().value); // '0'
 console.log(it.next().value); // '1'
 console.log(it.next().value); // '2'
 // ...
-
+``` -

ジェネレーターで

+### ジェネレーターで -
function* makeSimpleGenerator(array) {
+```js
+function* makeSimpleGenerator(array) {
   let nextIndex = 0;
-  while (nextIndex < array.length) {
+  while (nextIndex < array.length) {
     yield array[nextIndex++];
   }
 }
 
-let gen = makeSimpleGenerator(['yo', 'ya']);
+const gen = makeSimpleGenerator(['yo', 'ya']);
 
 console.log(gen.next().value); // 'yo'
 console.log(gen.next().value); // 'ya'
@@ -308,30 +311,31 @@ function* idMaker() {
   }
 }
 
-let gen = idMaker()
+const it = idMaker()
 
-console.log(gen.next().value); // '0'
-console.log(gen.next().value); // '1'
-console.log(gen.next().value); // '2'
+console.log(it.next().value); // '0'
+console.log(it.next().value); // '1'
+console.log(it.next().value); // '2'
 // ...
-
+```

ES2015 クラスで

-
class SimpleClass {
+```js
+class SimpleClass {
   constructor(data) {
     this.data = data;
   }
 
   [Symbol.iterator]() {
-    // Use a new index for each iterator. This makes multiple
-    // iterations over the iterable safe for non-trivial cases,
-    // such as use of break or nested looping over the same iterable.
+    // 各反復子に新しいインデックスを使用します。これにより、 break を使用したり
+    // 同じ反復可能オブジェクトに対する入れ子ループのような自明でない場合に、
+    // 反復可能オブジェクトに対する複数の反復処理を安全に行うことができます。
     let index = 0;
 
     return {
-      next: () => {
-        if (index < this.data.length) {
+      next: () => {
+        if (index < this.data.length) {
           return {value: this.data[index++], done: false}
         } else {
           return {done: true}
@@ -346,13 +350,14 @@ const simple = new SimpleClass([1,2,3,4,5]);
 for (const val of simple) {
   console.log(val); // '1' '2' '3' '4' '5'
 }
-
+``` -

ジェネレーターは反復子か反復可能か

+## ジェネレーターは反復子か反復可能か -

{{jsxref("Generator", "ジェネレーターオブジェクト", "", 1)}} は、反復子でも反復可能でもあります。

+{{jsxref("Generator", "ジェネレーターオブジェクト", "", 1)}} は、反復子でも反復可能でもあります。 -
let aGeneratorObject = function* () {
+```js
+const aGeneratorObject = function* () {
   yield 1;
   yield 2;
   yield 3;
@@ -369,26 +374,12 @@ console.log(aGeneratorObject[Symbol.iterator]() === aGeneratorObject);
 
 console.log([...aGeneratorObject]);
 // [1, 2, 3]
-
- -

仕様書

- - - - - - - - - - - -
仕様書
{{SpecName('ESDraft', '#sec-iteration', 'Iteration')}}
+console.log(Symbol.iterator in aGeneratorObject) +// true, because @@iterator method is a property of aGeneratorObject +``` -

関連情報

+## 関連情報 - +- {{jsxref("Statements/function*", "function* のドキュメント", "", 1)}} +- [Iteration in the ECMAScript specification](https://tc39.es/ecma262/#sec-iteration) -- cgit v1.2.3-54-g00ecf