(5장) 문 - 1. 표현문 2. 복합문과 빈 문 3. 조건문 4. 반복문 5. 점프문 [자바스크립트 완벽 가이드 7판]

iberis2·2023년 1월 9일
0

5장 문

[함께보면 좋은 글] 문(장)과 표현식
표현문(expression statement) : 할당, 함수 호출처럼 부수효과가 있는 표현식이자 문장
선언문(declaration statement) : 변수 선언 또는 함수 정의
제어문(control structure) : 동작의 기본 실행 순서를 바꾸는 문장

  • 조건문 : if, switch
  • 반복문(loop) : while, for
  • 점프 : break, return, throw

5-1. 표현문

할당문, ++ -- delete 연산자, 함수 호출 등

let myNum = 42;
myNum++;

let myFunction = function(){
  myNum--;
  console.log(myNum);
}

myFunction(); // 42

5-2. 복합문과 빈 문

복합문 { ; ; }

문 블록 { } 안에 ;세미 콜론으로 구분하여 여러 문을 하나의 복합문으로 묶을 수 있다.

  • {} 블록은 ;세미콜론으로 끝나지 않는다.
  • {} 블록 안에 들어 있는 각 문은 들여쓴다.
{
  x = Math.Pi;
  cx = Math.cos(x);
  console.log("con(𝜋) =" + cx);
}

빈 문

문 자리에 ; 만 작성
빈 바디를 갖는 반복문(loop)를 만들 때 주로 사용

const a = [1, 2, 3, 4, 5]; 
for(let i = 0; i<a.length; a[i++] = 0); 
// for문의 body 자리에 { } 대신 ; 사용 
// 이 for문의 의도는 a의 모든 요소들이 0으로 초기화하는 것

console.log(a); // [ 0, 0, 0, 0, 0 ]

5-3. 조건문

if

 if ( 조건1 ) { 
	조건1true일 때 동작;
  } else if ( 조건2 ) {
    조건2true일 때 동작;
  } else { 
  조건1, 조건2가 모두 false일 때 동작;
  }
  • if문을 중첩해서 쓸 때에는 else문이 의도했던 if 문과 연결 될 수 있도록
    { } 중괄호 및 들여쓰기를 주의해야한다.

switch

특정한 값과 일치(===)하는 지에 대한 조건을 만들 때 효과적이다.

  • switch문은 암시적 형 변환을 허용하지 않는다.
    즉, 뿐만아니라 타입도 같아야 한다.

case의 마지막에 break; 를 적어 일치하는 case에서 종료될 수 있도록 끝을 지정해주어야 한다.

  • 지정하지 않는 경우 일치하는 case부터 마지막 case (또는 default:)까지 모두 실행한다
  • 함수 안에서 switch문을 쓸 때에는 break 대신 return을 써도 된다.

어떤 case와도 일치하지 않는 경우 default: 를 실행한다.

  • 일반적으로 마지막 case의 뒤에 적지만 다른 위치에 적어도 정상적으로 작동한다.
// [심리테스트] 마음에 드는 동물을 골라주세요.
// 1 토끼 2 고양이 3 코알라 4 강아지

let myChoice = 2;

switch(myChoice) {
  case 1:
    console.log('토끼를 선택한 당신, ...');
    break;
  case 2:
    console.log('고양이를 선택한 당신, ...');
    break;
  case 3:
    console.log('코알라를 선택한 당신, ...');
    break;
  case 4:
    console.log('강아지를 선택한 당신, ...');
    break;
  default:
    console.log('1에서 4사이의 숫자를 선택해 주세요.'); 
}
// 고양이를 선택한 당신, ...

5-4. 반복문(loop)

while(조건){ 동작; }

① 조건문 밖에서 변수를 선언하여, 그 결과를 조건문 밖에서 사용할 때,
② 반복 횟수가 정해져있지 않을 때 사용 할 수 있다.

while(true)일 때 조건과 연관된 변수가 변하지 않는 경우 무한 루프에 빠지게 되므로
(무한 루프를 의도한 것이 아니라면)
루프를 반복할 때마다 변수가 바뀔 수 있도록 지정해줘야 한다.

// 30보다 큰 수 중 가장 작은 7의 배수는?
let i = 30; 
while(i % 7 !== 0){
  i++ 
}
console.log(i); // 35

do{ 동작; }while(조건);

동작을 실행 후 조건을 평가하기 때문에 적어도 1회 이상 동작을 실행한다.
while(조건) 문장의 마지막에 ; 세미콜론을 마지막에 반드시 붙여주어야 한다.

let i = 30;
do {
  i++;
} while (i % 7 !== 0); // 세미콜론 필수

console.log(i); // 35

for(변수 선언; 조건; 변수 변화){ 동작; }

변수 선언, 조건, 변수 변화 모두 생략할 수 있지만, ; 세미콜론은 필수이다.
조건 부분을 생략하면 무한 루프에 빠질 수 있다.

배열은 '동적'으로 순회하기 때문에 반복 도중 배열 자체에 변화가 생기면 반복 결과가 달라질 수 있다.

let myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

for (i = 0; i < myArray.length; i++) {
  myArray.splice(i, 1); // i번째 인덱스 1개 삭제 
}

console.log(myArray); // [ 2, 4, 6, 8, 10 ]
// 제일 처음 루프에서는 myArray[1] 은 2이지만, 1이 삭제 된 후 myArray[1] 은 3이다.

for(변수 of 배열 ){ 동작; }

of 의 왼쪽 변수에 배열의 모든 요소가 순회하며 할당된다.

배열(Array), 문자열(String), 세트(Set), 맵(Map)과 같은 이터러블(iterable) 객체에서 동작한다.
일반적인 객체에 for of 반복문을 사용할 경우 TypeError 발생한다.

  • Object.keys(객체), Object.values(객체), Objecct.Entries(객체)에서는 사용 가능

😄이모지는 UTF-16 문자 2 개로 이루어져 있어 length 가 2이지만,
(ES6 이후) 하나의 프로퍼티 네임으로, 이모지 1개당 1번의 반복을 실행한다.

console.log("😀".length); // 2


let myArray = ["😀", "♥︎", "a", "☺︎", 1];

let i = 0;
for (el of myArray) {
  i++;
  console.log(`${i}회 반복 : ${el}`);
}

/* 
1회 반복 : 😀
2회 반복 : ♥︎
3회 반복 : a
4회 반복 : ☺︎
5회 반복 : 1
*/

[함께보면 좋은 글] Map과 Set
Map 객체의 이터레이터는 키-값의 쌍을 순회한다.
첫 번째 요소가 키, 두번째 요소가 값인 배열을 순회한다.

let myMap = new Map();

myMap.set("1", "문자열 1");
myMap.set(2, "숫자형 2");
myMap.set(true, "불린형 트루");

console.log(myMap); 
// Map(3) { '1' => '문자열 1', 2 => '숫자형 2', true => '불린형 트루' }

for (let [key, value] of myMap) {
  console.log(`myMap의 키 ${key}은(는) ${typeof key} 타입이고, 값은 ${value} 입니다.`);
}

/* 
myMap의 키 1은(는) string 타입이고, 값은 문자열 1 입니다.
myMap의 키 2은(는) number 타입이고, 값은 숫자형 2 입니다.
myMap의 키 true은(는) boolean 타입이고, 값은 불린형 트루 입니다.
 */

for(변수 in 객체){ 동작; }

객체의 모든 key가 in 왼쪽의 변수에 순회하며 할당된다.
배열에 사용할 경우 인덱스 번호가 key역할을 한다.

  • 하지만 상황에 따라 버그가 발생할 수 있으므로, 배열은 for of 문을 사용하는 것이 대부분 더 적합하다.

다음 프로퍼티는 for in 문을 실행하더라도 열거되지 않는다.

  • 이름이 심벌인 프로퍼티
  • 이름이 문자열인 프로퍼티 중 열거 불가능한 프로퍼티
  • 자바스크립트에서 정의하는 내장 매서드
let myObj = { x: 1, y: 2, z: 3 };
for (key in myObj) {
  console.log(key);
  console.log(myObj[key]);
}

// x 1 y 2 z 3

5-5. 점프문

  • break : 반복문(loop) 또는 다른 문의 끝으로 이동
  • continue : 반복문(loop)의 해당 회차의 나머지를 생략하고 새로운 반복 시작
  • return : 함수를 빠져나와 값을 전달
  • yield : 제너레이터 함수에서 사용하는 return 비슷한 문
  • throw : 예외를 발생시킨다.
    • 예외가 발생하면 가장 가까운 예외 핸들러로 점프하는데, 핸들러는 동일한 함수 안에 있을 수도 있고 콜 스택을 거슬러 올라가 호출자에게 있을 수도 있다.
    • 예외 처리를 담당하는 try, catch, finally문과 함께 사용

label (라벨 또는 레이블)

label 이름:
주로 반복문(loop) 또는 조건문에서 사용한다.
label 을 사용하면, break 또는 continue를 만났을 때 label이 있는 곳으로 루프를 빠져나갈 수 있다.

let myAry = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]];

// laber 없이 break; 사용했을 때 : 가까운 loop만 빠져나간다.
for (let i = 0; i < myAry.length; i++) {
  for (let j = 0; j < myAry[i].length; j++) {
    if (myAry[i][j] === 22) {
      break;
    }
    console.log(myAry[i][j]);
  }
} // 11 12 13 14 21 31 32 33 34 41 42 43 44


// label을 사용했을 때 : 해당 label로 빠져나간다.
outloof: for (let i = 0; i < myAry.length; i++) {
  for (let j = 0; j < myAry[i].length; j++) {
    if (myAry[i][j] === 22) {
      break ouutloof;
    }
    console.log(myAry[i][j]);
  }
} // 11 12 13 14 21 
  • break(또는 continue)와 label 이름을 다른 줄에 쓰면 안된다.
    • 줄이 바뀌면 break; 자동으로 ; 세미 콜론 삽입된 것으로 인식
  • label 이름은 변수, 함수의 할당과 다르므로, label과 같은 이름으로 변수나 함수 이름을 지정할 수 있다.
  • 중첩되지 않는 문이라면 동일한 이름으로 label을 지정할 수도 있다.

break

자신을 포함한 가장 가까문 loop 또는 switch 문을 빠져나간다.
일반 { } 문 블록도 빠져나갈 수 있지만,
❌ label을 쓰더라도 함수 밖으로는 빠져나갈 수 없다.

function myFunction() {
  onelabel: {      // 조건문, 반복문이 아닌 일반 { } 도 빠져나갈 수 있다.
    console.log("normal");
    break onelabel;
    console.log("it wouldn't be printed");
  }
  console.log("Is it printed?");
}

myFunction(); 
/* normal 
   Is it printed? */


// 하지만 함수 밖으로는 빠져나갈 수 없다.
onelabel: function myFunction() { // 함수 밖으로 label 지정
  {     
    console.log("normal");
    break onelabel;
    console.log("it wouldn't be printed");
  }
  console.log("Is it printed?");
}

myFunction(); // SyntaxError: Undefined label 'onelabel'

continue

continue를 만나는 순간 현재 반복을 멈추고 다음 반복으로 넘어간다.

(label이 있든 없든) 반복문(loop) 바디 안에서만 사용할 수 있다.

  • 다른 곳에서 사용하면 SyntaxError가 발생한다.
for (j = 1; j < 5; j++) {
  if (j === 3) {
    continue;
  }
  console.log(j);
}     // 1 2 4

return

  • 함수의 호출 값을 반환하며, 함수의 바디 안에서만 쓸 수 있다.
    • 다른 곳에서 사용하면 SyntaxError가 발생한다.
  • 함수는 return 실행 즉시 함수는 종료되고 하위 다른 문(장)은 무시된다.
  • 반환하는 값 없이 return; 만 사용할 수도 있으며, 이 경우 undefined를 반환한다.
  • return반환하는 값 사이에 줄을 바꿀 수 없다.

throw, try catch (finally)

[함께 보면 좋은 글] Error와 예외 관리

5-6. 기타 문

with

지정된 객체의 프로퍼티가 해당 블록의 스코프 안에 있는 변수인 것처럼 코드 블록을 실행한다.
❌ 사용하지 않는 것이 좋다.

  • 최적화에 어렵다.
  • 느리게 동작한다.
  • 모호성이 생길 수 있다.

debugger

웹 브라우저에서 개발자 도구를 열고 debugger 프로그램을 통해 변수 값을 출력하거나 콜 스택을 살펴볼 수 있다.

use strict

strict 모드는 자바스크립트의 중요한 결함을 수정하고, 더 강력히 에러를 체크하며, 보안을 강화한 것이다.

  • 전체 스크립트 또는 특정 함수에 적용 가능하다.
    • 전체 스크립트에 적용하는 경우 스크립트 맨 처음, 함수에 적용하는 경우 바디의 맨 처음에만 존재할 수 있고, 이 앞에 실제 문이 있어서는 안된다.
  • class 바디, ES6 모듈 안에 있는 코드는 'use strict'을 명시적으로 사용하지 않았더라도 자동으로 strict 모드를 따른다.
  • 일반 모드와의 차이점
    • with문을 허용하지 않는다.
    • 반드시 모든 변수를 선언 후 사용할 수 있다.
      • 일반 모드에서는 전역 객체에 새 프로퍼티를 추가하는 방식으로 묵시적으로 전역 변수를 선언한다
// 일반 모드
x = 3;
console.log(x); // 3

// strict 모드
"use strict"; 
x = 3; // ReferenceError: x is not defined
console.log(x);
    • 함수로 호출된 함수의 this 값은 undefined 이다.
      • 일반 모드에서는 전역 객체이다.
    • 함수를 call()이나 apply()로 호출했을 때 this 값은 전달된 첫 번째 인자이다.
    • 일반 모드에서는 null 이나 undefined 값이 전역 객체로 대체되며 객체가 아닌 값은 객체로 변환된다.
    • 읽기 전용 프로퍼티에 할당, 확장 불가능한 객체에 새 프로퍼티 생성, 변경 불가(non-configurable) 프로퍼티 삭제(delete)하면 TypeError 발생한다.
      • 일반 모드에서는 에러는 발생하지 않고 그냥 실패한다.
    • delete 연산자 뒤 변수, 함수, 함수 매개변수 등 유효하지 않은 식별자를 사용하면 SyntaxError가 발생한다.
      • 일반 모드에서는 에러는 발생하지 않고 false로 평가된다.
    • 함수 선언에서 같은 이름의 매개변수가 2개 이상 있으면 SyntaxError 발생한다.

그 외 strict mode 더 확인하기 MDN

5-7. 선언

const, let, var

[함께 보면 좋은 글] 스코프와 호이스팅

함수

[함께 보면 좋은 글] 함수 선언문과 함수 표현식 차이

클래스

클래스 선언은 호이스팅 되지 않으며, 선언하기 전에 사용할 수 없다

import, export

함수나 클래스를 하나의 모듈안에서 정의한 후 export(내보내기)로 값을 내보내고,
사용하고 싶은 다른 모듈에서 import(가져오기)로 가져오면, 다른 모듈에서도 사용할 수 있다.

profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글