制御フロー

制御フローとは、JavaScript インタープリタが実行される順序です。 ステートメント。スクリプトにフローを変更するステートメントが含まれていない場合、 一度に 1 行ずつ実行されます。制御構造は、 一連のステートメントが実行されるかどうかを 一連のステートメントを繰り返し実行したり、 ステートメントのシーケンスです。

条件ステートメント

条件文は、1 つまたは複数の条件に基づいてコードを実行する 条件が表示されます条件文は、条件が満たされていれば、含まれているコードを実行して 関連付けられた条件(または一連の条件)は true と評価されます。それ以外の場合、 スキップされます。

if...else

if ステートメントは、一致したかっこ内の条件を評価します。 できます。かっこ内の条件が true と評価された場合、 ステートメントまたはブロック ステートメント 次の関数が実行されます。

if ( true ) console.log( "True." );
> "True."

if ( true ) {
    const myString = "True.";
    console.log( myString );
}
> "True."

かっこ内の条件が false と評価された場合、 は無視されます。

if ( false ) console.log( "True." );

if ステートメントの直後の else キーワードと 条件付き実行ステートメントは、特定の条件が満たされた場合に if 条件が false と評価される:

if ( false ) console.log( "True." )''
else console.log( "False" );
> "False."

複数の if ステートメントを連結するには、次のように記述します。 else に続く別の if ステートメントに続く条件付き実行ステートメント:

const myCondition = 2;
if ( myCondition === 5 ) console.log( "Five." );
else if ( myCondition === 2 ) console.log( "Two." );

その場合は、条件に続くブロック ステートメントの構文を使用することを強くおすすめします。 可読性が向上しますが、else if 句は例外となることがよくあります。

if ( myCondition === 5 ) {
    console.log( "Five." );
} else if ( myCondition === 3 ) {
    console.log( "Three" );
} else {
    console.log( "Neither five nor three." );
}
> "Neither five nor three."

3 項演算子

if は、条件付きでステートメントを実行します。3 項演算子(より正確に (3 項条件演算子)はあまり一般的には呼ばれません)は、省略形に使用されます。 条件に基づいて式を実行できます名前のとおり、3 項は 演算子は、次の 3 つのオペランドを使用する唯一の JavaScript 演算子です:

  • 評価する条件の後に疑問符(?)が続きます。
  • 条件が true と評価され、その後に続く場合に実行される式 コロン(:)。
  • 条件が false と評価された場合に実行される式。

これは、条件付きで値を設定または渡すためによく使用されます。

const myFirstResult  = true  ? "First value." : "Second value.";
const mySecondResult = false ? "First value." : "Second value.";

myFirstResult;
> "First value."

mySecondResult;
> "Second value."

switch...case

switch ステートメントを使用して、式の値を 1 つ以上の case キーワードを使用して定義された可能性のある値。この構文は、 JavaScript の初期の設計上の決定事項に基づいているからです。 switch...case 構文では、switch キーワードに続けて式を指定します。 かっこで囲まれた後に、対応する中かっこのペアが続きます。 switch の本文には case 個のキーワードを含めることができます(通常は 1 つ以上) その後に式または値、コロン(:)が続きます。

インタープリタが、式に一致する値を持つ case に到達すると、 switch キーワードの後のかっこで囲まれて評価されると、 case 句に続くステートメントは次のようになります。

switch ( 2 + 2 === 4 ) {
  case false:
    console.log( "False." );
  case true:
    console.log( "True." );
}
> "True."

一致する case に続くすべてのステートメントは、次のステートメントでも実行されます。 ブロック ステートメントで囲まれている。

switch ( 2 + 2 === 4 ) {
    case false:
    console.log( "False." );
  case true:
    let myVariable = "True.";
    console.log( myVariable );

}
> "True."

switch…case を使用する際の注意点として、一致が見つかった後に JavaScript インタープリタは、一致した case に続くすべてのステートメントを実行します。 他の case 句内のものも含まれます。これを「フォールスルー」と呼びます。宛先: 次の case:

switch ( 2 + 2 === 7 ) {
    case false:
    console.log( "False." );
  case true:
    console.log( "True." );
}
> "False."
> "True."

フォールバックを回避するには、各ケースを break キーワードで終了します。 switch 本文の評価をすぐに停止します。

switch ( 2 + 2 === 7 ) {
    case false:
    console.log( "False." );
    break;
  case true:
    console.log( "True." );
    break;
}
> "False."

条件値に一致する case がない場合、switchdefault を選択します。 指定することもできます。

switch ( 20 ) {
    case 5:
    console.log( "The value was five." );
    break;
  case 10:
    console.log( "The value was ten." );
    break;
  default:
    console.log( "The value was something unexpected." );
}
> "The value was something unexpected."

ただし、フォールバックは default にも適用されるため、 想定外の結果になることもありますこれを修正するには、default ステートメントを break で終了します。 ケースのリストの最後に置くこともできます。

switch ( 20 ) {
  default:
    console.log( "The value was something unexpected." );
  case 10:
    console.log( "The value was ten." );
    break;
  case 5:
    console.log( "The value was five." );
    break;
}
> The value was something unexpected.
> The value was ten.

case 句は グループ化のためのブロック ステートメント 複数のステートメント、case 句と default 句によって何も作成されない 語彙スコープ:

let myVariable;
switch ( true ) {
  case true:
    let myVariable = "True.";
    break;
  default:
    let myVariable = "False.";
    break;
}
> Uncaught SyntaxError: redeclaration of let myVariable

スコープを管理するには、ブロック ステートメントを使用します。

let myVariable;
switch ( true ) {
  case true: {
    let myVariable = "True.";
    break;
  }
  default: {
    let myVariable = "False.";
    break;
  }
}

ループとイテレーション

ループを使用すると、条件が満たされている限り、または複数のステートメントを繰り返すことができます。 トリガーされます。固定された命令セットを実行するループを 特定の結果が得られる / 通訳が指示するまでに 反復可能なデータ構造の最後に到達する(たとえば、 配列、マップ、またはセットであり、オブジェクトの最後のプロパティ、 。

ループは「上から下」の作業を中断するスクリプトの実行のフローを 1 つ以上の条件が満たされる または定義されなくなるまで ループの作成に使用する構文に応じて、いずれかの条件が満たされます。ループが終了すると 後続のステートメントまで実行されます。以下の例では、 ループの本文内のステートメントは、 通訳モード:

let iterationCount = 0;
console.log( "Pre-loop." );
while( iterationCount < 3 ) {
  iterationCount++;
  console.log( "Loop iteration." );
}
console.log( "Continuing on." );
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Continuing on."

ループの実行中に条件が満たされない場合、ループは続行されます。 制限はありませんプログラミングにおけるよくある落とし穴は、 メイン実行スレッドを引き起こす 無期限に一時停止したり ブラウザタブをクラッシュさせたりすることも可能です

次の例は、ブール値 true が維持されている限り実行されます trueブール値は不変であるため、 無限ループになります

console.log( "Pre-loop." );
while( true ) {
console.log( "Loop iteration." );
}
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
…

本番環境のコードに無限ループを残さないでください。誤って 実行中のブラウザタブを閉じて修正できます。 ループが無限にならないようにコードを更新してから、 できます。

while

while キーワードに続けて次のペアを使用して、while ループが作成されます。 照合する条件を含むかっこ。もし 条件は最初に true と評価されます。つまり、次のステートメント(または ブロック ステートメント)の後に続く部分で、 括弧が実行されます。そうでない場合、ループは実行されません。各 繰り返しで、条件が再評価され、まだ true の場合はループ 繰り返します。

let iterationCount = 0;
while( iterationCount < 3 ) {
  iterationCount++;
  console.log( `Loop ${ iterationCount }.` );
}
> "Loop 1."
> "Loop 2."

インタープリタは、while ループ内で continue ステートメントを見つけると、その処理を停止します。 反復処理が行われ、条件が再評価され、可能であればループが続行されます。

let iterationCount = 0;
while( iterationCount <= 5 ) {
  iterationCount++;
  if( iterationCount === 3 ) {
    continue;
  }
  console.log( `Loop ${ iterationCount }.` );
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Loop 4."
> "Loop 5."
> "Loop ended."

インタープリタが while ループ内で break ステートメントを見つけると、その反復処理は 停止し、条件は再評価されず、インタープリタは次に進みます。

let iterationCount = 1;
while( iterationCount <= 5 ) {
  if( iterationCount === 3 ) {
    console.log(`Iteration skipped.``);`
    break;
  }
  console.log( `Loop ${ iterationCount }.` );
  iterationCount++;
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Iteration skipped.
> "Loop ended."

次に示すように、while を使用すると、指定した回数だけ反復処理を行うことができます。 while の最も一般的なユースケースは、 不確定の長さ:

let randomize = () => Math.floor( Math.random() * 10 );
let randomNum = randomize();
while( randomNum !== 3 ){
  console.log( `The number is not ${ randomNum }.` );
  randomNum = randomize();
}
console.log( `The correct number, ${ randomNum }, was found.` );
> "The number is not 0."
> "The number is not 6."
> "The number is not 1."
> "The number is not 8."
> "The correct number, 3, was found."

do...while

do...while は、while ループのバリアントで、 評価はループの各反復処理の最後に行われます。つまり、 ループの本文は常に少なくとも 1 回実行されます。

do...while ループを作成するには、do キーワードに続けてステートメントを使用します。 (またはブロック ステートメント)を使用して、 ループの各反復処理で実行されます。そのステートメントの直後に while と、評価する条件を含む一致したかっこ。日時 この条件が true と評価されなくなると、ループは終了します。

let iterationCount = 1;
do {
  console.log( `Loop ${ iterationCount }.` );
  iterationCount++;
} while ( iterationCount < 3 );
> "Loop 1."
> "Loop 2."
> "Loop 3."

while ループと同様に、do...while の最も一般的なユースケースは、 不確定の長さ:

let randomNum;
do {
  randomNum = ( () => Math.floor( Math.random() * 10 ) )();
  console.log( `Is the number ${ randomNum }?` );
} while ( randomNum !== 3 );
console.log( `Yes, ${ randomNum } was the correct number.` );
> "Is the number 9?"
> "Is the number 2?"
> "Is the number 8?"
> "Is the number 2?"
> "Is the number 3?"
> "Yes, 3 was the correct number."

for

for ループを使用して、既知の数量を反復処理します。以前のコードベースでは、これは 配列内の要素の反復処理で頻繁に使用されます。

for ループを作成するには、for キーワードに続けてかっこのセットを使用します。 次の 3 つの式を順番に受け入れ、 セミコロン:

  1. ループ開始時に評価される式
  2. ループを続行するかどうかを決定する条件
  3. 各ループの最後に実行される式

これらのかっこの後に、次の文を追加します(通常は ブロック ステートメント)を使用して、 実行されます。

for( let i = 0; i < 3; i++ ) {
  console.log( "This loop will run three times.")
}

最初の式は、カウンタとして機能する変数を初期化します。この 式は、ループの最初の反復処理の前に 1 回評価されます。Google Chat では この変数は、他の変数と同様に let(または、従来は var)を使用して初期化します。 そのスコープはループの本体です。これらの変数には任意の 有効な識別子ですが、よく「反復処理」のために i と呼ばれます。指定します。 これは確立された 予測可能な識別子名のベスト プラクティス この規則は、他の開発者が理解できるように十分に確立されており、 ひと目でわかるようになります。インデックス付きコレクションはゼロのインデックス付きであるため、 これらの変数の初期値はほぼ常に 0 です。

他の形式のループと同様に、条件は、 ループを実行するかどうかを指定できます。これは通常、ファイアウォール ルールで イテレーション カウンタのバイト数です。インタープリタは、実行前に条件を for ループを最初に実行します。条件が最初に一致しない場合は、 true と評価された場合、ループの本体は実行されません。

最後の式は、ループの各反復処理の終了時に実行されます。 これは通常、識別子を 1 つ増やすために使用されます。

for ループは、古いバージョンの配列で反復処理を行うことがよくあります。 構築できます。このような場合、ループを続行するために指定する条件は、 反復処理の対象となる配列の長さ以下の反復回数 。現在の反復回数を追跡するために使用される変数は、 配列内のそのインデックスに関連付けられた値を増やし、 操作対象の配列を順番に並べます。

var myArray = [ true, false, true ];
for( let i = 0; i <= myArray.length; i++ ) {
  console.log( myArray[ i ] );
}
> true
> false
> true

このアプローチは使用されなくなったため、 反復可能なデータ構造をループする。

for [...] of [...]

for...of... ループを使用して、 反復可能なデータ構造(配列、セット、マップなど)。

for...of... ループでは、for キーワードに続けてかっこのセットを使用します。 変数を含み、その後に of、反復処理されるデータ構造 できます。変数は、ここで letconst、または var、現在のスコープ内で以前に宣言された変数、オブジェクト プロパティ、または 割り当ての分解。 これには、現在のイテレーションに対応する要素の値が含まれます。 実現します。

const myIterable = [ true, false, true ];
for( const myElement of myIterable ) {
  console.log( myElement );
}
> true
> false
> true

この例では、myElement が維持されていても、myElementconst を使用できます。 新しい値が渡されます。これは、変数が let または const で宣言されたコントロールは、スコープが あります。変数は反復処理の開始時に初期化され、反復処理の トリガーされます。

for...in...

for...in... ループを使用して、オブジェクトの列挙可能なプロパティを反復処理します。 これには列挙可能な継承プロパティも含まれますfor...of... ループと同様に、 for...in... ループは、for キーワードに続けてかっこのセットを使用します。 対応するプロパティキーの値を含む変数が 現在のループの反復処理で行われます。この変数の後に、 in キーワードの場合、イテレーションされるオブジェクトは次のようになります。

const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
  console.log( myKey );
}
> "myProperty"
> "mySecondProperty"

繰り返しになりますが、myKey の値はループの反復処理ごとに変わります。 変数が実質的に破棄されるため、const をエラーなしで使用できる 各反復処理の最後に生成され、開始時に再作成されます。

各プロパティキーに関連付けられた値を、 for...in... の構文。ただし、ループはプロパティ キーにアクセスできるため、 そのキーを使用して「検索」できます。値:

const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
  const myValue = myObject[ myKey ];
  console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "mySecondProperty : false"

組み込みコンストラクタから継承されたプロパティは列挙不可です。つまり、 for...in... は Object から継承されたプロパティを反復処理しません。 コンストラクタがあります。ただし、オブジェクトの プロトタイプ チェーンが含まれます。

const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
    myProperty: {
    value: true,
    enumerable: true
    }
});
for ( const myKey in myObject ) {
  const myValue = myObject[ myKey ];
  console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "protoProperty : true"

JavaScript には、プロパティが オブジェクトのプロトタイプのプロパティではなく、オブジェクトの直接プロパティです。 モダン Object.hasOwn() メソッドと以前の Object.prototype.hasOwnProperty() メソッド。これらの メソッドは、指定されたプロパティが継承されている(または宣言されていない)かどうかを評価します。 指定されたオブジェクトの直接のプロパティに対してのみ true を返す:

const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
    myProperty: {
    value: true,
    enumerable: true
    }
});
for ( const myKey in myObject ) {
  const myValue = myObject[ myKey ];
  if ( Object.hasOwn( myObject, myKey ) ) {
    console.log( `${ myKey } : ${ myValue }` );
  }
}
> "myProperty : true"

また、3 つの静的メソッドもあり、それぞれ オブジェクトの列挙可能なキー(Object.keys())、値(Object.values())、または Key-Value ペア(Object.entries()):

const myObject = { "myProperty" : true, "mySecondProperty" : false };
Object.keys( myObject );
> Array [ "myProperty", "mySecondProperty" ]

これにより、オブジェクト キー、値、または Key-Value ペアを 割り当ての分解) オブジェクトのプロトタイプが所有するプロパティを含めずに、

const myPrototype = { "protoProperty" : "Non-enumerable property value." };
const myObject = Object.create( myPrototype, {
    myProperty: {
    value: "Enumerable property value.",
    enumerable: true
    }
});

for ( const propKey of Object.keys( myObject ) ) {
  console.log( propKey );
}
> "myProperty"

for ( const propValue of Object.values( myObject ) ) {
  console.log( propValue );
}
> "Enumerable property value."

for ( const [ propKey, propValue ] of Object.entries( myObject ) ) {
  console.log( `${ propKey } : ${ propValue }` );
}
> "myProperty : Enumerable property value."

forEach()

Array が提供する forEach() メソッド。 MapSet、 NodeList コンストラクタを使用すると、データを反復処理するのに役立つ コールバック関数のコンテキスト内で呼び出します。他の形式のループとは異なり、 forEach()メソッドで作成されたループは、breakまたは continue

forEach は、各データ構造のプロトタイプが所有するメソッドです。各forEach メソッドはコールバック関数を引数として想定しますが、 引数のキーワードだけを抽出できます。もう 1 つはオプションです。 引数は、リソースの呼び出し元のコンテキストとして使用する this 値を指定します。 使用します。

Array.forEach で使用されるコールバック関数には、 現在の要素の値、現在の要素のインデックス、forEach メソッドが呼び出された配列:

const myArray = [ true, false ];
myArray.forEach( ( myElement, i, originalArray ) => {
  console.log( i, myElement, originalArray  );
});
> 0 true Array(3) [ true, false ]
> 1 false Array(3) [ true, false ]

Map.forEach で使用されるコールバック関数は、 値、現在の要素に関連付けられているキー、 要素、forEach メソッドが呼び出された地図:

const myMap = new Map([
  ['myKey', true],
  ['mySecondKey', false ],
]);
myMap.forEach( ( myValue, myKey, originalMap ) => {
    console.log( myValue, myKey, originalMap  );
});
> true "myKey" Map { myKey → true, mySecondKey → false }
> false "mySecondKey" Map { myKey → true, mySecondKey → false }

Set.forEach コールバックには、同様のパラメータが含まれます。Set には インデックスまたは値とは異なるキーを指定する場合、2 番目の引数に 厳密に維持するために、冗長で無視可能な値を指定します。 その他の forEach メソッド。

const mySet = new Set([ true, false ]);
mySet.forEach( ( myValue, myKey, originalSet ) => {
  console.log( myValue, myKey, originalSet  );
});
> true true Set [ true, false ]
> false false Set [ true, false ]

イテレータ

iterable は、変換可能な個々の要素で構成されるデータ構造です。 繰り返しました。イテレータイテレータ プロトコルに従うイテレータ オブジェクト。つまり、 next() メソッドで、含まれている要素を 1 つずつ順に処理します。 そのメソッドが呼び出されるたびに、連続する各メソッドに対して 特定の形式で返されます。

JavaScript に組み込まれているイテラブル データ構造( 配列Map Set など)は、 ただし、これらはすべて iterator メソッドを継承しており、 @@iterator よく知られた記号、 これは、イテラブル データ構造から作成されたイテレータ オブジェクトを返します。

const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();

myIterable;
> (3) [1, 2, 3]

myIterator;
> Array Iterator {}

イテレータの next() メソッドを呼び出すと、イテレータの要素がステップ表示されます。 一度に 1 つ含まれ、各呼び出しは 2 つの要素を含む 1 つのオブジェクトを返します。 プロパティ: 現在の要素の値を含む value done: イテレータが最後の要素を渡したかどうかを示すブール値 学びました。done の値が true になるのは、next() への呼び出しが行われた場合のみです。 は、末尾の要素を超える要素へのアクセスを試行します。 イテレータになります。

const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();

myIterator.next();
> Object { value: 1, done: false }

myIterator.next();
> Object { value: 2, done: false }

myIterator.next();
> Object { value: 3, done: false }

myIterator.next();
> Object { value: undefined, done: true }

ジェネレータ関数

function* キーワード(アスタリスクに注意)を使用してジェネレータを宣言する ジェネレータ関数式を定義するか、

function* myGeneratorFunction() { };

イテレータと同様に、ジェネレータ関数は状態を維持します。スマートフォンの Generator 関数は新しい Generator オブジェクトを返すが、すぐには返さず 関数の本文でコードを実行します。

function* myGeneratorFunction() {
  console.log( "Generator function body ")
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject;
> Generator {  }

typeof myGeneratorObject;
> "object"

ジェネレータ オブジェクトはイテレータ プロトコルに従います。呼び出しの各値 ジェネレータ関数の戻り値の next() は、yield 式によって決まります。 これはジェネレータ関数の実行を一時停止し、 キーワード yield を含む式を返します。その後の next() の呼び出し 次の yield 式で一時停止して関数の実行を続行し、 関連する値を返します。

function* myGeneratorFunction() {
  yield "My first yielded value.";
  yield "My second yielded value.";
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> Object { value: "My first yielded value.", done: false }

myGeneratorObject.next();
> Object { value: "My second yielded value.", done: false }

yield を使用してこれ以上値を指定せずに next() が呼び出されると、 return または throw(エラーの場合)は、関数の残りの部分 body が実行され、返されたオブジェクトには undefinedvaluedone が含まれる true のプロパティ:


function* myGeneratorFunction() {
    console.log( "Start of the generator function." );
    yield "First";
    console.log( "Second part of the generator function."  );
    yield "Second";
    console.log( "Third part of the generator function." );
    yield "Third";
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> "Start of the generator function."
> Object { value: "First", done: false }

myGeneratorObject.next();
> "Second part of the generator function."
> Object { value: "Second", done: false }

myGeneratorObject.next();
> "Third part of the generator function."
> Object { value: "Third", done: false }

myGeneratorObject.next();
> Object { value: undefined, done: true }

next() は、ジェネレータ関数が返すオブジェクトにのみ使用します。 生成します。それ以外の場合、ジェネレータ関数を呼び出すたびに 新しいジェネレータ オブジェクトを作成します。

function* myGeneratorFunction() {
  yield "First";
  yield "Second";
};

myGeneratorFunction().next();
> Object { value: "First", done: false }

myGeneratorFunction().next();
> Object { value: "First", done: false }

他の関数と同様に、ジェネレータ関数は return を検出すると停止します。 できます。その後、オブジェクトを含む呼び出し元のコンテキストに done プロパティ(値 true)が返されます。

function* myGeneratorFunction() {
  yield 1;
  yield 2;
  return 3;
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next().done;
> Object { value: 1, done: false }

myGeneratorObject.next().done;
> Object { value: 2, done: false }

myGeneratorObject.next();
> Object { value: 3, done: true }

yield 式は、識別子のセマンティクスの一部を取ることができます。 双方向の「通信」が可能停止部分まで戻ります 生成します。ジェネレータの next() メソッドに値が渡されると、 引数がある場合、以前の停止中の yield 式:

function* myGeneratorFunction() {
    const firstYield = yield;
    yield firstYield + 10;
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> Object { value: undefined, done: false }

myGeneratorObject.next( 5 );
> Object { value: 15, done: false }

これは 以前の yield の値を以前の yield に再割り当てするのではなく、 next() で指定された値:

function* myGeneratorFunction() {
    const firstYield = yield;
    const secondYield = yield firstYield + 100;
    yield secondYield + 10;
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> Object { value: undefined, done: false }

myGeneratorObject.next( 10 ); // Can be thought of as changing the value of the `firstYield` variable to `10
> Object { value: 110, done: false }

myGeneratorObject.next( 20 ); // Can be thought of as changing the value of the `secondYield` variable to `20`, _not_ `20 + 100;`
> Object { value: 30, done: false }

next() の最初の呼び出しに渡される引数はいずれも無視されるため、無視されます。 その値を受け入れる yield 式。他の関数と同様に 最初のジェネレータ関数呼び出しに渡される引数は、 ジェネレータ関数の本文のスコープを指定します。

function* myGeneratorFunction( startingValue ) {
    let newValue = yield startingValue + 1;
    newValue = yield newValue + 10;
    yield startingValue + 20;
};
const myGeneratorObject = myGeneratorFunction( 2 );

myGeneratorObject.next( 1 );
> Object { value: 3, done: false }

myGeneratorObject.next( 5 );
> Object { value: 15, done: false }

myGeneratorObject.next( 10 );
Object { value: 22, done: false }

yield*(アスタリスク)演算子は、次のようにイテラブルで使用されます。 別のジェネレータ関数で、オペランドを反復処理して各値を生成します。 戻り値:

function* mySecondaryGenerator() {
  yield 2;
  yield 3;
}

function* myGenerator() {
  yield 1;
  yield* mySecondaryGenerator();
  yield 4;
  return 5;
}

const myIterator = myGenerator();

myIterator.next();
> Object { value: 1, done: false }

myIterator.next();
> Object { value: 2, done: false }

myIterator.next();
> Object { value: 3, done: false }

myIterator.next();
> Object { value: 4, done: false }

myIterator.next();
> Object { value: 5, done: true }

非同期 JavaScript

JavaScript は基本的に同期的な動作ですが、 実行時に利用できるメカニズムが用意されているため、 実行するイベントループ タスクを自動化できます。

Promise

Promise は、Promise が置き換えられた時点では不明な値のプレースホルダ 作成されます。このコンテナは、非同期オペレーション、すなわち Google Cloud の そのオペレーションが成功または失敗と見なされる場合、 その結果の値。

組み込みの Promisenew 演算子を使用して Promise インスタンスを作成する コンストラクタ関数を使用します。このコンストラクタは、エグゼキュータという関数を受け取ります。 渡します。このエグゼキュータ関数は、通常、1 つ以上の 次に、Promise で使用する条件を 自動的に処理されますPromise は保留中として定義されます。 エグゼキュータ関数の実行中です。エグゼキュータが終了すると、Promise 完了(ドキュメントによっては、解決済み)とみなされます。 エグゼキュータ関数とそれが実行する非同期アクションの完了 正常に終了し、エグゼキュータ関数にエラーが発生した場合は拒否されます。 非同期アクションが失敗しますPromise の達成後または 不承認となった場合、決済済みと見なされます。

const myPromise = new Promise( () => { });

コンストラクタは、2 つの引数を使用してエグゼキュータ関数を呼び出します。これらの引数は、 Promise を手動で実行または拒否できる関数です。

const  myPromise = new Promise( ( fulfill, reject ) => { });

Promise の実行または拒否に使用される関数は、結果の Promise の値(通常は拒否の場合はエラー):

const myPromise = new Promise( ( fulfill, reject ) => {
  const myResult = true;
  setTimeout(() => {
    if( myResult === true ) {
        fulfill( "This Promise was successful." );    
    } else {
        reject( new Error( "This Promise has been rejected." ) );
    }
  }, 10000);
});

myPromise;
> Promise { <state>: "pending" }

myPromise;
> Promise { <state>: "fulfilled", <value>: "This Promise was successful." }

Promise チェーン

結果の Promise オブジェクトは、then()catch()、および Promise コンストラクタから継承された finally() メソッド。これらの メソッドは Promise を返します。Promise は then() で直ちに処理できます。 catch() または finally() を再度使用して、結果の Promise を連結できます。

then() は、引数として 2 つのコールバック関数を提供します。1 つ目の これを拒否する 2 番目です。どちらの方法でも 1 つの 結果の Promise に値を渡す引数です。

const myPromise = new Promise( ( fulfill, reject ) => {
  const myResult = true;
  setTimeout(() => {
    if( myResult === true ) {
        fulfill( "This Promise was fulfilled." );    
    } else {
        reject( new Error( "This Promise has been rejected." ) );
    }
  }, 100);
});

myPromise.then( successfulResult => console.log( successfulResult ), failedResult => console.error( failedResult ) );
> "This Promise was successful."

また、then() を使用して処理済み状態のみを処理し、catch を使用して処理済み状態のみを処理することもできます。 自動的に処理されます。引数を 1 つ指定して catch を呼び出します。 Promise の拒否メソッドで指定された値が使用されます。

const myPromise = new Promise( ( fulfill, reject ) => {
  const myResult = false;
  setTimeout(() => {
    if( myResult === true ) {
        fulfill( "This Promise was fulfilled." );    
    } else {
        reject( new Error( "This Promise has been rejected." ) );
    }
  }, 100);
});

myPromise
  .then( fulfilledResult => console.log(fulfilledResult ) )
  .catch( rejectedResult => console.log( rejectedResult ) )
  .finally( () => console.log( "The Promise has settled." ) );
> "Error: This Promise has been rejected."
> "The Promise has settled."

Promise の実行時にハンドラ関数を実行できる then および catch とは異なり、 満たまたは拒否されると、関数が引数として finally に渡される メソッドは Promise が履行されたか拒否されたかにかかわらず呼び出されます。 ハンドラ関数は、引数なしで呼び出されます。これは、 Promise から渡された値を使用して処理し、 これで約束は完了です。

同時実行

Promise コンストラクタには、関連する複数のオブジェクトを処理する 4 つのメソッドが Promise オブジェクトを含む iterable を使用します。これらの 各メソッドは Promise を返します。この Promise は、状態に基づいて解決または拒否されます。 渡された Promise の総称です。たとえば、Promise.all() は Promise を作成します。 このメソッドは、このメソッドに渡されたすべての Promise が履行された場合にのみ履行されます。

const firstPromise  = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const secondPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const thirdPromise  = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const failedPromise = new Promise( ( fulfill, reject ) => reject( "Failed.") );
const successfulPromises = [ firstPromise, secondPromise, thirdPromise ];
const oneFailedPromise = [ failedPromise, ...successfulPromises ];

Promise.all( successfulPromises )
  .then( ( allValues ) => {
    console.log( allValues );
  })
  .catch( ( failValue ) => {
    console.error( failValue );
  });
> Array(3) [ "Successful. ", "Successful. ", "Successful. " ]

Promise.all( oneFailedPromise  )
    .then( ( allValues ) => {
      console.log( allValues );
    })
    .catch( ( failValue ) => {
     console.error( failValue );
    });
> "Failed."

Promise の同時実行メソッドは次のとおりです。

Promise.all()
指定されたすべての Promise が履行された場合にのみ、履行されます。
Promise.any()
指定された Promise のいずれかが満たされた場合に完了し、のみ拒否されます すべての Promise が拒否された場合にスローされます。
Promise.allSettled()
結果に関係なく、Promise が解決すると履行されます。
Promise.race()
最初に解決する Promise の結果に基づいて却下または履行される。 後で解決した Promise をすべて無視します。

async/await

関数宣言の前に async キーワードを使用する場合 または関数式、任意の その関数が返す値は、そのフィールドを含む完成された Promise として返されます。 あります。これにより、同じ API キーを使用して非同期オペレーションを実行、管理できます。 ワークフローを同期開発として実装できます

async function myFunction() {
  return "This is my returned value.";
}

myFunction().then( myReturnedValue => console.log( myReturnedValue ) );
> "This is my returned value."

await 式は、非同期関数の実行を一時停止します。 関連付けられている Promise が解決されます。Promise が解決されると、 await 式は、Promise の解決または拒否された値です。

async function myFunction() {
  const myPromise  = new Promise( ( fulfill, reject ) => { setTimeout( () => fulfill( "Successful. "), 5000 ); });
  const myPromisedResult = await myPromise;
  return myPromisedResult;
}

myFunction()
  .then( myResult => console.log( myResult ) )
  .catch( myFailedResult => console.error( myFailedResult ) );
> "Successful."

await 式に含まれる Promise 以外の値は、 達成された約束:

async function myFunction() {
  const myPromisedResult = await "String value.";
  return myPromisedResult;
}

myFunction()
  .then( myResult => console.log( myResult ) )
  .catch( myFailedResult => console.error( myFailedResult ) );
> "String value."

理解度をチェックする

既知の数量を反復処理するには、どのようなループを使用しますか。

for
while
do...while