본 강의는 Programmers의 Hello, JavaScript: 자바스크립트 입문 강의를 기반으로 작성되었으나, 작성자에 의견에 따라 일부 내용이 추가되거나 수정되어 작성된 포스트입니다
if
, if/else
, else if
)조건문은 조건식( condition
)이 참( true
)일 경우 해당 코드 블록을 실행한다. 만약 거짓이라면 해당 코드 블록은 실행되지 않는다.
if
가장 기본적인 코드다. condition
이 참일 경우 코드 블록을 실행한다.
if (condition) {
// 코드 블록
}
아래 예제를 살펴보자.
let x = 15;
if (x > 10) {
console.log("x는 10보다 큽니다");
// [output] x는 10보다 큽니다
}
위 예제에서 if
문 안의 조건문, x > 10
이 참( true
) 이므로 x는 10보다 큽니다
가 출력된다.
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보다 작거나 같습니다
가 출력된다.
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보다 큽니다");
실행
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()
로 출력해주는 예제다.
while
, do while
)조건( condition
)에 따라 코드 블록을 반복적으로 수행한다.
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)
의 condition
은 prompt
에 exit
이 입력됙 전까지 true
이므로, 메뉴를 사용자가 원할때까지 추가할 수 있다.
while
문에서도 break;
를 사용해 코드 블록을 빠져나올 수 있다.
while
에서 continue
를 사용하면 현재 반복을 중지하고, 다음 반복을 처음부터 진행한다.
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} 원`);
for
, for in
)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
로 초기화 하고, i
가 5
보다 작다면 조건문을 실행한 후, i
의 값을 1
증가 시키는 for
문이다.
다만, for
을 사용하는 경우 별도의 변수의 값을 이용해 배열의 위치를 확인할 수 밖에 없다. (index
를 이용한다)
횟수가 정해져 있는 반복문일 경우:
for
을 사용
정해져 있지 않은 반복문일 경우:while
을 사용
하는 것이 가독성을 높일 수 있다.
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
을 사용해야 한다.
자세한 내용은 변수의 선언 방식에 대해 설명할 때 알아보았다. 자세한 내용은 여기서 확인해보자.
변수의 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) 발생 가능성 때문에 권장되지는 않는다)
method
)와 this
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()
에서 name
과age
를 출력하고 싶어한다.
이 때 name
과 age
는 greet
메소드가 속한 person
이라는 객체에 값이 존재하는데, greet
에서 이 객체 속성에 대한 값에 접근하기 위해 this
를 사용해주면 쉽게 접근이 가능하다.
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
, ...
를 출력할 수 있다.