프로그래밍 언어의 중요한 요소인 Control Flow에 대해서 정리해보려고 한다. 추가로 기본적인 연산자들에 대해서도 함께 정리하였다.
"기본 연산자? 그거 누구나 알고 있는 것들 아니야?" 라고 생각할 수 있다. 하지만, 나는 작은 것들이 쌓여서 큰 산을 이룬다고 믿는 사람이다. 또한, 작은 지나침들이 쌓여 큰 실수를 만들어냄을 두려워하기도 한다. 기본이라고 무시했다가 버그에 시달리지 말고 미리미리 차곡차곡 기본도 놓치지 말아보자. 그래서 간단하지만 잊어서는 안되는 기본 연산자들도 살펴보자.
(쉬운 알고리즘을 풀다가 간단한 것들을 놓쳐 생고생한 기억이 있다...🥲 천재가 아니라면 작은 것도 다시 보자 🥺 물론, 내 실력이 부족해서 그렇다. )
여러 문자열들을 연결하는 방법들이 몇 가지가 있다. 예시를 보면 아래와 같다.
console.log("my" + " cat"); // my cat
console.log("1" + 2); // 12
console.log(`string literals: 1 + 2 = ${1 + 2}`); // string literals: 1 + 2 = 3
JavaScript
는 저번 포스팅에서도 말했던 것처럼 Dynamically typed language
이기 때문에 실행될 때 동적으로 타입을 정한다. 두 번째 줄에서 "1" + 2
의 경우에 숫자 2를 문자열로 변경해서 문자열 1과 문자열 2과 붙은 12가 되었다. 나누기나 곱셈 연산의 경우에는 문자열을 숫자로 변경하여 진행이 된다.
string literals
의 방법을 사용하면 ${ }
을 통해서 변수나 연산자와 함께 문자열을 쉽게 사용할 수 있으므로 기억해두면 좋다.
( 굳이, " cat"
와 같이 합쳐진 경우의 공백까지 염두에 두고 작성할 필요가 없다. )
숫자 연산은 프로그래밍 언어가 아니라고 해도 표현법이 크게 다르지 않다.
console.log(1 + 1); // add : 2
console.log(1 - 1); // substract : 0
console.log(1 / 1); // divide : 1
console.log(1 * 1); // multiply : 1
console.log(5 % 2); // remainder : 1
console.log(2 ** 3); // exponentiation : 8
변수에 할당된 값을 1 감소시키거나 증가시킬 때 사용하는 연산자이다. 상황에 따라 다르게 적용할 수 있다.
let counter = 2;
const preIncrement = ++counter;
console.log(`preIncrement: ${preIncrement}, counter: ${counter}`);
// 결과는 preIncrement: 3, counter: 3
// counter에 1을 증가시키는 것이 먼저 실행!
const postIncrement = counter++; // counter = 3인 상태!
console.log(`postIncrement: ${postIncrement}, counter: ${counter}`);
// 결과는 postIncrement: 3, counter: 4
// counter에 1을 증가시키는 것보다 postIncrement에
// counter의 값을 할당하는 것이 먼저 실행!
JavaScript
에는 고맙게도 x = x + y
등을 간단하게 표현할 수 있는 할당 연산자가 존재한다.
할당 연산자 | 사례 | 동일 표현 |
---|---|---|
= | x = y | x = y |
+= | x += y | x = x + y |
-= | x -= y | x = x - y |
*= | x *= y | x = x * y |
/= | x /= y | x = x / y |
프로그래밍 언어를 다루다 보면 boolean logic
을 다루는 경우가 많다. 꼭 프로그래밍 아니라고 해도 참을 뜻하는 true
나 거짓을 뜻하는 false
의 값들은 논리적인 연산들을 구성할 때 어디서든 빠질 수 없는 요소이다. 비교 연산자는 주어진 값들을 비교하여 참이나 거짓으로 return 할 수 있기 때문에 매우 유용하다.
비교 연산자 | 이름 | 예시 | 결과값 |
---|---|---|---|
> | greater than | 10 > 6 | true |
>= | greater than or equal to | 10 >= 6 | true |
< | less than | 10 < 6 | false |
<= | less than or equal to | 10 <= 6 | false |
== | equal to | 3 == '3' | true |
!= | not equal to | 3 != 2 | true |
=== | equal value and type | 3 === '3' | false |
!== | not equal value or equal type | 3 !== '3' | true |
위의 예시를 보면 ==
와 ===
의 차이에 대해서 알 수 있다. ==
의 경우에는 loose equality
로 type conversion
을 진행해 두 개의 3
이 동일하다고 판단했고 ===
의 경우에는 strict equality
로 타입이 다르기 때문에 동일하지 않다고 판단했다. 특별한 이유가 없다면 더 엄격한 ===
을 사용하기를 권장한다.
비교 연산자와 마찬가지로 여러가지 논리적인 연산들을 구성할 때 빠질 수 없는 것이 논리 연산자이다. 엘리님은 많은 주니어들이 시니어 개발자분들에게 피드백을 받는 부분이라고 말씀하셨다.
논리 연산자에는 || (or)
과 && (and)
, ! (not)
이 있다.
|| (or)
연산자는 true
값을 좋아한다. 무슨 소리냐고 하겠지만 true
값을 찾으면 연산을 멈춘다는 뜻이다.
let A = true;
let B = false;
let C = "I don't care"
console.log(A || B || C);
위의 예시에서 B나 C가 어떤 값을 가지고 있는지는 중요하지 않다. 이미 A가 true
을 가지고 있기 때문에 더 이상 연산을 수행하지 않고 true
를 return
한다. 정말 True Lover(finds the first truthy value) 이다.
&& (and)
연산자는 || (or)
과는 다르게 비관론자스럽다. 하나의 실패라도 있다면 바로 포기한다. && (and)
연산자는 false
를 만나는 순간 연산을 중단하고 'false'을 return
한다.
💡 Point!
두 연산자는true
나false
를 만나는 순간 연산을 중단하고 결과값을 return 하기 때문에 연산이 오래걸리는 조건의 경우에는 최대한 뒤에 배치하는 것이 좋다. 동일한 결과값을 얻기 위해서 더 많은 시간을 사용하는 것은 효율적이지 못하다! 기억하자. Simple conditions first!!
! (not)
연산자는 값을 반대 값으로 변환하여 return
해준다.
위에서 정리한 여러가지 비교연산자나 논리연산자 등을 통해서 조건에 따라 다른 동작을 실행할 수 있도록 하는 것이 if
이다.
const name = "cheoljin";
if (name === "cheoljin") {
console.log("Welcome, cheoljin!");
} else if (name === "coder") {
console.log("You are amazing coder");
} else {
console.log("unknown");
}
위의 예시의 결과로는 Welcome, cheoljin!
이 나온다. 만약 name에 "coder"
고 할당되어 있다면 if
의 조건을 만족하지 못하기 때문에 else if
으로 넘어간다. else if
의 조건은 일치하기 때문에 You are amazing coder
이 출력된다. 아무런 조건도 만족하지 못하는 값이 들어온다면 else
안에 있는 unknown
이 출력된다.
정리해보면 if
조건이 true
가 된다면 block
안에 있는 코드들이 실행이 되고 false
가 된다면 else if
으로 넘어간다. else if
조건에도 동일한 판단이 이루어지고 false
의 경우에는 else
의 block
안에 있는 코드를 실행한다. 아래처럼 여러 개의 else if
를 사용할 수도 있다.
if ( 조건 1) {
동작1
} else if ( 조건 2) {
동작2
} else if ( 조건 3) {
동작3
} else if ( 조건 4) {
동작4
} else {
마지막... 이제 그만!
}
물론 위의 방법은 추천하고 싶지 않다. 여러 개의 else if
를 사용하는 경우에는 switch
를 고려해보자.
삼항 연산자는 if...else
를 간단하게 표현할 수 있다.
console.log(name === 'cheoljin' ? 'yes' : 'no');
다른 표현식의 일부로서 사용할 수 있기 때문에 유용하다. 다만, 계속 중첩하여 사용하는 경우라면 삼항 연산자가 아닌 if
나 switch
를 사용하는 것이 가독성에서도 좋다.
switch
는 여러 케이스의 경우에 다른 출력 값을 내보내고 싶을 때 사용하면 좋다.
const browser = "IE";
switch (browser) {
case "IE":
console.log("go away!");
break;
case "Chrome":
case "Firefox":
console.log("love you!");
break;
default:
console.log("same all!");
break;
}
break
는 true
값을 가진 case
를 만났을 때 해당하는 코드를 실행한 뒤에 block
을 탈출하게 해준다. 만약 위의 코드에서 break
가 없다면 true
을 만난 곳부터 이후의 모든 코드가 실행된다. 이것은 우리가 원하지 않는 결과이기 때문에 break
를 꼭 써주자.
default
의 경우에는 모든 case
가 false
일 때 실행된다.
같은 작업을 여러 번 반복 시키고 싶을 때 while
, for
등의 반복문을 사용한다. 만약, 제한을 걸지 않는다면 무한으로 반복하다가 프로그램이 뻗을 수 있기 때문에 사용에 주의가 필요하다.
let i = 3;
while (i > 0) {
console.log(`while: ${i}`);
i--;
}
위의 예시를 보면 i
가 0보다 큰 경우에 block
안의 코드를 계속 실행한다는 것을 알 수 있다. 이 때, block
안에 i--
을 통해서 i
값이 1씩 감소하도록 해서 3번만 반복하도록 제한을 걸어두었다.
만약, 조건에 상관 없이 block
안의 코드를 한 번은 실행하도록 하고 싶다면 do while loop
를 사용하면 된다.
do {
console.log(`do while: ${i}`);
i--;
} while (i > 0);
do while loop
를 사용하면 block
안의 코드를 먼저 실행한 후에 조건을 확인한다.
추가로 while(true) 을 통해 무한 루프를 돌리는 경우도 있는데 이 때는 break
를 통해서 멈출 수 있도록 제한해야 한다.
반복문에는 for
도 있다. while
은 반복해야하는 횟수를 모르는 경우에 주로 사용하고 for
의 경우에는 반복해야하는 횟수가 정해져 있는 경우에 주로 사용한다.
// 기본 문법
for(begin; condition; step){
//실행하고자 하는 코드
}
기본 문법은 위와 같다. 예시를 보자.
for (i = 3; i > 0; i--) {
console.log(`for: ${i}`);
}
// 결과값
// for: 3
// for: 2
// for: 1
i
에 초기값으로 3을 주었고 0보다 큰 경우에 반복하도록 했다. 마지막으로는 횟수를 제어할 수 있도록 i
값이 1씩 감소하도록 했다. 그 결과 3번 실행됐다.
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
console.log(`i: ${i}, j: ${j}`);
}
}
for
를 위처럼 중첩해서 사용할 수도 있다. 하지만 위의 경우에 10의 제곱만큼의 반복이 일어나기 때문에 시간적인 단점이 있다. 피할 수 있다면 2중 for문
을 사용하지 않는 것을 권장한다.
for
에도 continue
나 break
를 사용할 수 있다. 간단한 예시를 보자.
for (let i = 0; i < 11; i++) {
if (i % 2 === 1) {
continue;
} else {
console.log(`q1: ${i}`);
}
}
continue
는 break
처럼 block
를 탈출하도록 하는 역할을 하지만 반복문 자체를 탈출하는 break
와는 다르게 해당하는 경우만 탈출하여 반복문을 계속 실행한다. 위의 경우에는 i % 2 === 1
을 만족하는 홀수의 경우에는 즉시 if
를 탈출한 후에 다음 반복문을 진행하였다. 그래서 짝수만을 출력할 수 있었다.
( 실제로 짝수만을 출력하고 싶은 경우에는 위의 방법보다 원하는 값만 출력하도록 코드를 작성하는 것이 좋다. 예시를 위해 위처럼 작성하였다.)
for (let i = 0; i < 10; i++) {
if (i > 8) {
break;
} else {
console.log(`q2: ${i}`);
}
}
i
가 8보다 큰 경우에는 반복문이 멈추도록 하였다. 위의 예시들처럼 continue
와 break
를 통해서 반복문을 더욱 편리하게 제어할 수 있다.
참고자료:
드림코딩 by 엘리