Javascript 입문 - 005. if , switch , while , for

You Seunghyeon·2023년 3월 10일
0

Javascript 입문

목록 보기
5/6

본 강의는 Programmers의 Hello, JavaScript: 자바스크립트 입문 강의를 기반으로 작성되었으나, 작성자에 의견에 따라 일부 내용이 추가되거나 수정되어 작성된 포스트입니다

01. 조건문( if, if/else, else if )

조건문은 조건식( condition )이 참( true )일 경우 해당 코드 블록을 실행한다. 만약 거짓이라면 해당 코드 블록은 실행되지 않는다.

01.01. if

가장 기본적인 코드다. condition 이 참일 경우 코드 블록을 실행한다.

if (condition) {
  // 코드 블록
}

아래 예제를 살펴보자.

let x = 15;

if (x > 10) {
  console.log("x는 10보다 큽니다");
  // [output] x는 10보다 큽니다
}

위 예제에서 if 문 안의 조건문, x > 10이 참( true ) 이므로 x는 10보다 큽니다 가 출력된다.

01.02. if/else

if 문의 조건식이 참이 아닐 경우, else 문을 실행한다.

if (condition) {
  // 조건식이 참일 때 실행할 코드 블록
} else {
  // 조건식이 거짓일 때 실행할 코드 블록
}

아래 예제를 살펴보자.

let x = 5;

if (x > 10) {
  console.log("x는 10보다 큽니다");
} else {
  console.log("x는 10보다 작거나 같습니다");
}

위 예제에서는 x 의 값은 5 이므로, if 문의 x > 10 조건에 만족하지 않는다. 따라서 x는 10보다 작거나 같습니다 가 출력된다.

01.03. else if

else if 문은 여러 개의 조건을 체크할 때 사용된다. 순차적으로 조건을 확인하며, 만약 마지막까지 참이 없을 경우 else 문을 실행한다.

if (condition1) {
  // 조건식1이 참일 때 실행할 코드 블록
} else if (condition2) {
  // 조건식2가 참일 때 실행할 코드 블록
} else if (condition3) {
  // 조건식3이 참일 때 실행할 코드 블록
} else {
  // 모든 조건이 거짓일 때 실행할 코드 블록
}

아래 예제를 살펴보자.

let x = 7;

if (x > 10) {
  console.log("x는 10보다 큽니다");
} else if (x > 5) {
  console.log("x는 5보다 큽니다");
} else {
  console.log("x는 5보다 작거나 같습니다");
}

위 예제에서는 아래와 같이 진행된다.
1. if (x > 10) = false
2. else if (x > 5) = true
3. console.log("x는 5보다 큽니다"); 실행

02. 조건문(switch)

switch 문은 주어진 값에 대해 여러 조건( case )를 비교해 해당하는 조건의 코드 블록을 실행한다.

아래처럼 사용한다.

switch (expression) {
  case value1:
    // 실행할 코드 블록
    break;
  case value2:
    // 실행할 코드 블록
    break;
  //...
  default:
    // 모든 조건이 일치하지 않을 때 실행할 코드 블록
}

expression 은 비교할 값이고, 각 case 마다 value 값에 맞는 코드 블록이 실행된다.

break 는 각 case 문이 끝나면 반드시 적어줘야 한다. break 는 해당 case 의 코드 블록을 실행한 후, switch 에서 빠져나오도록 한다.

default 는 만약 모든 case 가 일치하지 않을 경우 실행하는 코드 블록이다. 이는 선택적으로 사용할 수 있다.

아래 예제를 살펴보자.

let operator = prompt("연산자를 입력하세요. (+, -, *, /)");

let num1 = Number(prompt("첫 번째 숫자를 입력하세요."));
let num2 = Number(prompt("두 번째 숫자를 입력하세요."));

let result;

switch (operator) {
  case "+":
    result = num1 + num2;
    break;
  case "-":
    result = num1 - num2;
    break;
  case "*":
    result = num1 * num2;
    break;
  case "/":
    result = num1 / num2;
    break;
  default:
    alert("잘못된 연산자입니다");
}

alert("계산 결과: " + result);

위 예제는 간단한 사칙연산 계산기를 switch 문을 이용해 만든 것이다.

또 다른 예제를 살펴보자.

console.log("Menu");
console.log("1. Ice Americano");
console.log("2. Cafe Latte");
console.log("3. Cappuccino");
console.log("4. Tea");

let choice = parseInt(prompt("메뉴 선택"));

console. log(choice + "번 메뉴 선택됨");

switch (choice) {
  case 1:
    console.log("아이스 아메리카노 / 1500원");
    break;
  case 2:
    console.log("카페 라떼 / 1800원");
    break;
  case 3:
    console.log("카푸치노 / 2000원");
    break;
  case 4:
    console.log("홍차 / 1300원");
    break;
  default:
    console.log("존재하지 않는 메뉴");
	break;
}

위는 prompt() 로 입력받은 메뉴가 무엇인지 console.log() 로 출력해주는 예제다.

03. 반복문(while, do while)

조건( condition )에 따라 코드 블록을 반복적으로 수행한다.

03.01. while

형식은 다음과 같다.

while (condition) {
  // 반복적으로 실행할 코드 블록
}

switch 문의 두번째 예제를 약간 바꿔보자. 기존에는 일회성으로 실행됬지만, 이제는 사용자가 원할때까지 메뉴를 담고, exit 을 입력하면 종료와 동시에 최종 가격을 제시하도록 구현해보자.

console.log("Menu");
console.log("1. Ice Americano");
console.log("2. Cafe Latte");
console.log("3. Cappuccino");
console.log("4. Tea");

let total = 0
let cart = {
  "아이스 아메리카노": 0,
  "카페 라떼": 0,
  "카푸치노": 0,
  "홍차": 0,
}

let isEnd = false;

while(!isEnd) {
  let choice = prompt("메뉴 선택");
  switch (choice) {
    case "1":
      console.log("아이스 아메리카노 / 1500원");
      cart["아이스 아메리카노"] += 1;
      total += 1500;
      break;
    case "2":
      console.log("카페 라떼 / 1800원");
      cart["카페 라떼"] += 1;
      total += 1800;
      break;
    case "3":
      console.log("카푸치노 / 2000원");
      cart["카푸치노"] += 1;
      total += 2000;
      break;
    case "4":
      console.log("홍차 / 1300원");
      cart["홍차"] += 1;
      total += 1300;
      break;
    case "exit":
      isEnd = true;
      break;
    default:
      console.log("존재하지 않는 메뉴");
  	  break;
    }
}

console.log("======= 정 산 =======");
console.log(`아이스 아메리카노: ${cart["아이스 아메리카노"]} 잔`);
console.log(`카페 라떼: ${cart["카페 라떼"]} 잔`);
console.log(`카푸치노: ${cart["카푸치노"]} 잔`);
console.log(`홍차: ${cart["홍차"]} 잔`);
console.log("--------");
console.log(`총 ${total} 원`);

위 예제처럼 while(!isEnd)conditionpromptexit 이 입력됙 전까지 true 이므로, 메뉴를 사용자가 원할때까지 추가할 수 있다.

while 문에서도 break;를 사용해 코드 블록을 빠져나올 수 있다.

while 에서 continue 를 사용하면 현재 반복을 중지하고, 다음 반복을 처음부터 진행한다.

03.02. do while

do while 문은 while 과 유사하지만, 조건식의 검사를 반복문의 마지막에 수행한다. 즉, 최초 한번은 무조건 실행하고, 그 다음에도 또 실행할지는 한번 더 돌기 전에 확인한다.

형식은 다음과 같다.

do {
  // 최소한 한 번 실행될 코드 블록
} while (condition);

위 예제를 변형하면 아래와 같이 사용할 수 있다.

console.log("Menu");
console.log("1. Ice Americano");
console.log("2. Cafe Latte");
console.log("3. Cappuccino");
console.log("4. Tea");

let total = 0
let cart = {
  "아이스 아메리카노": 0,
  "카페 라떼": 0,
  "카푸치노": 0,
  "홍차": 0,
}

let isEnd = false;
do {
  let choice = prompt("메뉴 선택");
  switch (choice) {
    case "1":
      console.log("아이스 아메리카노 / 1500원");
      cart["아이스 아메리카노"] += 1;
      total += 1500;
      break;
    case "2":
      console.log("카페 라떼 / 1800원");
      cart["카페 라떼"] += 1;
      total += 1800;
      break;
    case "3":
      console.log("카푸치노 / 2000원");
      cart["카푸치노"] += 1;
      total += 2000;
      break;
    case "4":
      console.log("홍차 / 1300원");
      cart["홍차"] += 1;
      total += 1300;
      break;
    case "exit":
      isEnd = true;
      break;
    default:
      console.log("존재하지 않는 메뉴");
  	  break;
    }
} while(!isEnd);

console.log("======= 정 산 =======");
console.log(`아이스 아메리카노: ${cart["아이스 아메리카노"]} 잔`);
console.log(`카페 라떼: ${cart["카페 라떼"]} 잔`);
console.log(`카푸치노: ${cart["카푸치노"]} 잔`);
console.log(`홍차: ${cart["홍차"]} 잔`);
console.log("--------");
console.log(`총 ${total} 원`);

04. 반복문 (for, for in)

04.01. for

for 문은 일반적으로 가장 많이 사용하는 반복문이다. 기본적으로 while 과 비슷하다.for 문에는 초기화식, 조건식, 증감식이 들어가며, 해당 조건에 맞을 경우 코드 블록을 실행한다.

형식은 다음과 같다.

for ([initialization]; [condition]; [final-expression]) {
  // 반복적으로 실행할 코드 블록
}

초기화(initialization): 반복문이 시작될 때 단 한 번 실행 되는 구문
조건식(condition): 반복문이 실행될 때 마다 검사할 조건, 참( true )일 경우 반복문이 실행
증감식(final-expression): 반복문이 실행될 때 마다 실행되는 구문

초기화는 항상 실행된다.

아래 예제를 살펴보자.

for (let i = 1; i <= 5; i++) {
  console.log(i);
  // [output] 1
  // [output] 2
  // [output] 3
  // [output] 4
  // [output] 5
}

변수 i 를 선언과 동시에 1 로 초기화 하고, i5 보다 작다면 조건문을 실행한 후, i 의 값을 1 증가 시키는 for 문이다.

다만, for 을 사용하는 경우 별도의 변수의 값을 이용해 배열의 위치를 확인할 수 밖에 없다. (index 를 이용한다)


횟수가 정해져 있는 반복문일 경우: for 을 사용
정해져 있지 않은 반복문일 경우: while 을 사용
하는 것이 가독성을 높일 수 있다.

04.02. for in

for in 은 객체의 속성이나 배열의 요소를 반복할 때 더욱 편리하게 사용할 수 있다.

index 를 이용할 수 밖에 없는for 문과 달리, for in 은 속성명 등을 사용할 수 있다.

형식은 다음과 같다.

for (var in obj) {
  // 반복적으로 실행할 코드 블록
}

아래 예제를 살펴보자.

let obj = {
  a: 1,
  b: 2,
  c: 3
};

let keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
  let prop = keys[i];
  console.log(prop + ': ' + obj[prop]);
}

이 예제에서는 obj 라는 객체의 속성에 접근하기 위해 Object.keys() 함술르 사용해 객체의 속성명들을 배열로 만들고, 그 배열의 길이만큼 for 문을 실행한다. 그리고 실행될 때 마다 i 의 값에 +1 하고, 배열의 길이보다 길어지면 반복문을 중지한다.

너무 비효율적이지 않은가?

아래 예제와 비교해보자.

let obj = {
  a: 1,
  b: 2,
  c: 3
};

for (let prop in obj) {
  console.log(prop + ': ' + obj[prop]);
}

(TIP. 속성명 in 객체명 을 사용하면 속성명이 객체 안에 있는지를 불리언 Boolean 값으로 반환해준다)

위 예제는 for in 을 활용해 작성한 코드다. 훨씬 가독성이 높고, 효율적이지 않은가? 따라서, 적절한 상황에 따라 while, do while, for, for in 을 사용해야 한다.

05. 변수의 scope

자세한 내용은 변수의 선언 방식에 대해 설명할 때 알아보았다. 자세한 내용은 여기서 확인해보자.

06. 변수의 shadowing

변수의 shadowing은 변수 이름이 중복되어 발생하는 문제다. 블록 내부에서 동일한 이름의 변수가 선언되면, 해당 블록에서는 내부에서 선언된 변수가 우선적으로 참조된다. 이 때, 외부에서 선언된 변수는 블록 내부에서 가려지게(shadowing) 되어 외부 변수를 참조할 수 없다.

아래 예제를 살펴보자.

let num = 10;

if (true) {
  let num = 5;
  console.log(num); // 내부 num 변수 참조
  // [output] 5
}

console.log(num); // 외부 num 변수 참조
// [output] 10

따라서, 함수 안에서만 값이 유지되어야 되는 경우 블록 스코프(Block Scope) 범위를 갖고 있는 let 또는 const 보다 함수 스코프(Function Scope)의 범위를 갖고 있는 var 를 사용하면 된다.
(다만 스코프 예측이 어렵고, 호이스팅(hoisting) 발생 가능성 때문에 권장되지는 않는다)

07. 메소드(method)와 this

07.01. 메소드(method)

메소드는 객체가 갖고 있는 함수를 의미한다. 예전에 설명한 것 처럼 객체에는 다양한 타입이 값으로 들어갈 수 있는데, 이 때 함수가 그 값으로 들어간 것을 의미한다.

이 때 메소드 내부에서 this 키워드는 해당 메소드가 속한 객체를 가리킨다.

아래 예제를 살펴보자.

let person = {
  name: "John",
  age: 30,
  greet: function() {
    console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
  }
};

person.greet(); // Hello, my name is John and I am 30 years old.

여기서 greet 은 메소드고, console.log() 에서 nameage 를 출력하고 싶어한다.

이 때 nameagegreet 메소드가 속한 person 이라는 객체에 값이 존재하는데, greet 에서 이 객체 속성에 대한 값에 접근하기 위해 this 를 사용해주면 쉽게 접근이 가능하다.

08. 클로저(closure)

클로저는 함수(parent) 내부에서 생성된 변수와 함수(child)는 해당 함수(parent)가 호출될 때마다 새롭게 생성이 되며, 생성된 여러 함수의 독립성을 유지할 수 있다.

아래 예제를 살펴보자.

function makeCounter() {
  let count = 0;
  return function() {
    count++;
    console.log(count);
  };
}

let counter1 = makeCounter();
counter1(); // 1
counter1(); // 2
counter1(); // 3

let counter2 = makeCounter();
counter2(); // 1
counter2(); // 2

여기서 보면 makeCounter() 함수가 총 두개(counter1, counter2) 생성되는데, 이 두 함수의 내부 변수와 함수 모두 다 독립성을 유지해 각각 1, 2, ... 를 출력할 수 있다.

0개의 댓글