제어 흐름

제어 흐름은 JavaScript 인터프리터가 실행되는 순서입니다. 합니다. 스크립트에 흐름을 변경하는 문이 포함되어 있지 않으면 한 번에 한 줄씩 실행됩니다 컨트롤 구조는 특정 데이터에 따라 일련의 문이 실행되는지 여부를 일련의 명령문을 반복적으로 실행하거나, 작업을 중단시킬 수 있습니다. 시퀀스입니다.

조건문

조건문은 다음 중 하나를 기준으로 코드를 실행해야 하는지 여부를 결정합니다. 확인할 수 있습니다 조건문은 다음과 같은 경우에 포함된 코드를 실행합니다. 관련 조건 (또는 조건 집합)은 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."

삼항 연산자

if는 문을 조건부로 실행합니다. 3항 연산자 (더 정확하게 주로 3항 조건부 연산자라고 함)이 약어로 사용됩니다. 조건부로 표현식을 실행합니다. 이름에서 알 수 있듯이 3항은 연산자는 세 개의 피연산자를 사용하는 유일한 자바스크립트 연산자입니다.

  • 평가할 조건 다음에 물음표 (?)가 옵니다.
  • 조건이 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 문을 사용하여 표현식의 값을 하나 이상의 case 키워드를 사용하여 정의된 잠재적 값 이 구문은 이는 JavaScript의 초기 설계 결정에서 비롯된 것이기 때문입니다. switch...case 구문은 switch 키워드 다음에 다음 표현식을 사용합니다. 괄호로 묶여 평가되고 그 뒤에 일치하는 중괄호 쌍이 옵니다. switch의 본문에는 case 키워드(일반적으로 하나 이상)가 포함될 수 있습니다. 그 뒤에 표현식 또는 값, 콜론 (:)이 옵니다.

인터프리터가 표현식과 일치하는 값이 있는 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 절에는 그룹화를 위한 블록 문 여러 문에서 casedefault 절이 생성되지 않음 어휘 범위 자체는 다음과 같습니다.

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;
  }
}

루프 및 반복

루프를 사용하면 조건이 충족되는 한 일련의 문을 반복할 수 있습니다. '시간 제한'을 설정합니다 루프를 사용하여 고정된 일련의 명령을 실행 특정 결과를 얻을 때까지 또는 통역사가 반복 가능한 데이터 구조의 끝에 도달 (예: 배열, 맵 또는 집합, 객체의 최종 속성 또는 문자열)입니다.

루프는 '상단에서 하단'으로 스크립트 실행 흐름을 하나 이상의 조건이 충족될 때까지 또는 더 이상 충족되지 않을 수도 있습니다 루프가 끝나면 그 뒤에 오는 문으로 계속 실행됩니다. 다음 예에서 루프 본문의 문은 코드가 실행되기 전에 통역사가 넘어갑니다.

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로 평가되면 문 (또는 block 문)을 해당 괄호가 실행됩니다. 그렇지 않으면 루프가 실행되지 않습니다. 각 반복하면 조건이 재평가되며 여전히 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 루프의 변형입니다. 각 루프 반복의 에서 평가가 이루어집니다. 즉, 항상 최소 한 번 이상 실행됩니다.

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 키워드 뒤에 괄호를 사용합니다. 는 세미콜론:

  1. 루프가 시작될 때 평가할 표현식입니다.
  2. 루프를 계속할지 여부를 결정하는 조건
  3. 각 루프가 끝날 때 실행될 표현식

이 괄호 뒤에 문 (일반적으로 block 문)을 자동으로 실행됩니다

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

첫 번째 표현식은 카운터 역할을 하는 변수를 초기화합니다. 이 표현식은 루프의 첫 번째 반복 전에 한 번 평가됩니다. 다음과 같은 작업을 할 수 있습니다. 다른 변수처럼 let (또는 이전에는 var)를 사용하여 이 변수를 초기화합니다. 변수의 범위는 루프의 본문입니다. 이러한 변수에는 유효한 식별자이지만 '반복'을 위해 i라고 자주 불립니다. 또는 '색인'입니다. 이는 기존 정책과 상반되는 것으로 보임 예측 가능한 식별자 이름에 대한 권장사항, 그러나 이 규범은 Google의 다른 개발자들이 이해할 수 있을 만큼 충분히 확립되어 있습니다. 한 눈에 볼 수 있습니다. 색인이 생성된 컬렉션의 색인은 0이므로 이러한 변수는 거의 항상 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가 나온 후 반복되는 데이터 구조 있습니다. 변수는 let, const 또는 var - 현재 범위 내에서 이전에 선언된 변수 속성 또는 디스트럭처링 할당을 참조하세요. 현재 반복에 해당하는 요소의 값을 포함합니다. 루프를 벗어날 수 있습니다.

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

이 예에서는 myElementconstmyElement 루프가 반복될 때마다 새 값이 지정됩니다. 이는 여러 변수가 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"

자바스크립트는 속성이 객체 프로토타입의 속성이 아닌 객체의 직접 속성 체인: modern 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"

또한 객체의 열거 가능한 키 (Object.keys()), 값 (Object.values()) 또는 키-값 쌍 (Object.entries()):

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

이렇게 하면 객체 키, 값 또는 키-값 쌍( 디스트럭처링 할당) 객체의 프로토타입이 소유한 속성을 포함하지 않고 다음과 같이 처리합니다.

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() 메서드 지도, 세트, NodeList 생성자는 데이터 반복을 위한 유용한 약식 표기를 제공합니다. 구조체로 구성해야 합니다. 다른 형태의 루프와 달리 forEach() 메서드로 생성된 루프는 break 또는 continue입니다.

forEach는 각 데이터 구조의 프로토타입이 소유한 메서드입니다. forEach마다 메서드는 콜백 함수를 인수로 예상하지만, 인수는 해당 함수가 호출될 때 포함된 인수의 항을 반환합니다. 두 번째는 선택사항입니다 인수는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 메서드가 호출된 Map:

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은 두 번째 인수는 대신 중복되고 무시할 수 있는 값을 모두 사용하여 다른 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 ]

Iterator

반복 가능한 데이터 구조는 이전에 설명한 접근 방식을 사용하여 반복했습니다. 반복자반복기 프로토콜을 따르는 반복 가능한 객체입니다. 즉, 포함된 요소를 한 번에 하나씩 진행하는 next() 메서드 해당 메서드가 호출될 때마다 요소를 특정 형식으로 포함할 수 있습니다.

JavaScript에 내장된 반복 가능 데이터 구조 (예: 배열, 지도 Set)는 이러한 클래스는 모두 iterator 메서드를 상속하며, 이 메서드는 @@iterator 잘 알려진 기호, 반복 가능한 데이터 구조에서 생성된 반복기 객체를 반환합니다.

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

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

myIterator;
> Array Iterator {}

반복기에서 next() 메서드를 호출하면 요소가 단계별로 실행됩니다. 한 번에 하나씩 포함되며, 각 호출은 두 개가 포함된 객체를 반환합니다. 속성: 현재 요소의 값을 포함하는 valuedone: 이터레이터가 살펴봤습니다 done 값은 next() 호출 시에만 true입니다. 의 마지막 요소 다음의 요소에 액세스하려고 시도합니다. 반복자입니다.

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() { };

반복자와 마찬가지로 생성기 함수는 상태를 유지합니다. 전화 생성기 함수가 새 생성기 객체를 반환하지만 즉시 함수 본문의 코드를 실행합니다.

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 (오류 발생 시), 함수의 나머지 본문이 실행되고 반환된 객체에 value undefineddone가 있음 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를 발견하면 중단됩니다. 있습니다. 그런 다음 값 및 값이 truedone 속성을 반환했습니다.

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

자바스크립트는 기본적으로 동기식이지만 개발자가 Google Cloud의 애플리케이션 프로그래밍 언어(LLM)를 수행할 이벤트 루프 비동기 작업을 수행합니다

프로미스

프로미스는 프로미스가 변경될 때 알 수 없는 값의 자리표시자입니다. 생성됨. 이것은 비동기 작업을 지시하는 컨테이너입니다. 성공 또는 실패로 간주되는 경우 취해야 할 조치 그리고 그 결과로 생성되는 값을 입력합니다.

기본 제공 Promise와 함께 new 연산자를 사용하여 프로미스 인스턴스를 만듭니다. 생성자 함수로 전달됩니다. 이 생성자는 executor라는 함수를 수락합니다. 를 인수로 사용합니다. 이 executor 함수는 일반적으로 하나 이상의 작업을 실행하는 데 사용됩니다. 프라미스 처리 기준을 정하고 성공적으로 처리되거나 거부된 것으로 간주됩니다. 프로미스는 대기 중으로 정의됩니다. executor 함수가 실행되는 동안 실행될 수 있습니다 실행자가 완료된 후 프로미스 다음과 같은 경우 처리됨 (또는 일부 문서 소스에서 해결됨)으로 간주됩니다. executor 함수와 이 함수가 수행하는 비동기 작업이 완료됩니다. 실행자 함수에 오류가 발생하면 거부됩니다. 수행 중인 비동기 작업이 실패합니다 프로미스가 처리된 후 또는 확정된 것으로 간주됩니다.

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

생성자는 두 개의 인수를 사용하여 executor 함수를 호출합니다. 이러한 주장은 프로미스를 직접 처리하거나 거부할 수 있는 기능입니다.

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

프로미스를 처리하거나 거부하는 데 사용되는 함수는 그 결과 프로미스 값을 인수로 사용합니다 (일반적으로 거부 시 오류).

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." }

프로미스 체이닝

결과 프로미스 객체는 then(), catch(), 프로미스 생성자에서 상속되는 finally() 메서드 이러한 각 메서드는 then()를 사용하여 즉시 조치를 취할 수 있는 프로미스를 반환합니다. catch() 또는 다시 finally()를 사용하면 결과 프로미스를 체인할 수 있습니다.

then()는 두 개의 콜백 함수를 인수로 제공합니다. 첫 번째 항목을 사용하여 처리하세요. 그 결과 프로미스가 되고 두 번째는 이를 거부합니다. 두 메서드 모두 단일 호출 인수를 반환합니다.

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를 사용하여 처리할 수도 있습니다. 처리할 수 있습니다. 다음을 포함하는 단일 인수로 catch를 호출합니다. 값은 프로미스의 거부 메서드에 제공된 값입니다.

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."

프로미스가 프로비저닝될 때 핸들러 함수를 실행할 수 있게 해주는 thencatch와는 다릅니다. 처리되거나 거부되면 함수가 finally에 인수로 전달됩니다. 메서드는 프로미스가 처리되었는지 또는 거부되었는지 여부와 상관없이 호출됩니다. 핸들러 함수는 인수 없이 호출됩니다. 인수 없이 호출되는 것은 프로미스에서 전달된 값으로 작업하고, 프로미스가 완료되었습니다.

동시 실행

프로미스 생성자는 관련된 여러 메서드를 사용하기 위한 네 가지 메서드를 제공합니다. 프로미스: 프로미스 객체를 포함하는 반복 가능 항목을 사용합니다. 이러한 메서드는 각각 상태에 따라 처리되거나 거부되는 프로미스를 반환합니다. 프로미스의 값을 정의합니다. 예를 들어 Promise.all()는 프로미스를 만듭니다. 해당 메서드로 전달된 모든 프라미스가 이행되는 경우에만 처리됩니다.

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.all()
제공된 모든 프로미스가 충족된 경우에만 처리됩니다.
Promise.any()
제공된 프로미스 중 하나라도 충족된 경우 처리되며 거부됨 (모든 프로미스가 거부되는 경우)
Promise.allSettled()
결과와 관계없이 프로미스가 정산되면 처리됩니다.
Promise.race()
첫 번째 해결 약속의 결과에 따라 거부 또는 처리됨 무시하는 것입니다.

async/await

함수 선언 앞에 async 키워드를 사용하는 경우 또는 함수 표현식, 모든 값 함수가 반환하는 값이 값으로 사용됩니다. 이렇게 하면 동일한 웹 기반 인터페이스를 사용하여 비동기 작업을 동기 개발로 사용합니다

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

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

await 표현식은 비동기 함수의 실행을 일시중지하지만 관련 프로미스가 정산되는 것을 볼 수 있습니다. 프로미스가 정산되면 await 표현식은 프로미스의 처리 또는 거부된 값입니다.

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 표현식에 포함된 비프로미스 값은 모두 성취된 프라미스:

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