TIL 017 | JavaScript Control Flow

JU CHEOLJIN·2021년 7월 7일
1

JavaScript

목록 보기
4/13
post-thumbnail

프로그래밍 언어의 중요한 요소인 Control Flow에 대해서 정리해보려고 한다. 추가로 기본적인 연산자들에 대해서도 함께 정리하였다.

기본 연산자

"기본 연산자? 그거 누구나 알고 있는 것들 아니야?" 라고 생각할 수 있다. 하지만, 나는 작은 것들이 쌓여서 큰 산을 이룬다고 믿는 사람이다. 또한, 작은 지나침들이 쌓여 큰 실수를 만들어냄을 두려워하기도 한다. 기본이라고 무시했다가 버그에 시달리지 말고 미리미리 차곡차곡 기본도 놓치지 말아보자. 그래서 간단하지만 잊어서는 안되는 기본 연산자들도 살펴보자.
(쉬운 알고리즘을 풀다가 간단한 것들을 놓쳐 생고생한 기억이 있다...🥲 천재가 아니라면 작은 것도 다시 보자 🥺 물론, 내 실력이 부족해서 그렇다. )

String concatenation

여러 문자열들을 연결하는 방법들이 몇 가지가 있다. 예시를 보면 아래와 같다.

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" 와 같이 합쳐진 경우의 공백까지 염두에 두고 작성할 필요가 없다. )

Numeric operators

숫자 연산은 프로그래밍 언어가 아니라고 해도 표현법이 크게 다르지 않다.

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

Increment & decrement operators

변수에 할당된 값을 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의 값을 할당하는 것이 먼저 실행!

Assignment operators

JavaScript에는 고맙게도 x = x + y 등을 간단하게 표현할 수 있는 할당 연산자가 존재한다.

할당 연산자사례동일 표현
=x = yx = y
+=x += yx = x + y
-=x -= yx = x - y
*=x *= yx = x * y
/=x /= yx = x / y

Comparison operator

프로그래밍 언어를 다루다 보면 boolean logic을 다루는 경우가 많다. 꼭 프로그래밍 아니라고 해도 참을 뜻하는 true나 거짓을 뜻하는 false의 값들은 논리적인 연산들을 구성할 때 어디서든 빠질 수 없는 요소이다. 비교 연산자는 주어진 값들을 비교하여 참이나 거짓으로 return 할 수 있기 때문에 매우 유용하다.

비교 연산자이름예시결과값
>greater than10 > 6true
>=greater than or equal to10 >= 6true
<less than10 < 6false
<=less than or equal to10 <= 6false
==equal to3 == '3'true
!=not equal to3 != 2true
===equal value and type3 === '3'false
!==not equal value or equal type3 !== '3'true

위의 예시를 보면 ===== 의 차이에 대해서 알 수 있다. == 의 경우에는 loose equalitytype conversion 을 진행해 두 개의 3이 동일하다고 판단했고 === 의 경우에는 strict equality 로 타입이 다르기 때문에 동일하지 않다고 판단했다. 특별한 이유가 없다면 더 엄격한 === 을 사용하기를 권장한다.

Logical operator

비교 연산자와 마찬가지로 여러가지 논리적인 연산들을 구성할 때 빠질 수 없는 것이 논리 연산자이다. 엘리님은 많은 주니어들이 시니어 개발자분들에게 피드백을 받는 부분이라고 말씀하셨다.

논리 연산자에는 || (or)&& (and) , ! (not) 이 있다.

|| (OR)

|| (or) 연산자는 true 값을 좋아한다. 무슨 소리냐고 하겠지만 true 값을 찾으면 연산을 멈춘다는 뜻이다.

let A = true;
let B = false;
let C = "I don't care"
console.log(A || B || C);

위의 예시에서 B나 C가 어떤 값을 가지고 있는지는 중요하지 않다. 이미 A가 true을 가지고 있기 때문에 더 이상 연산을 수행하지 않고 truereturn 한다. 정말 True Lover(finds the first truthy value) 이다.

&& (and)

&& (and) 연산자는 || (or) 과는 다르게 비관론자스럽다. 하나의 실패라도 있다면 바로 포기한다. && (and) 연산자는 false 를 만나는 순간 연산을 중단하고 'false'을 return 한다.

💡 Point!
두 연산자는 truefalse를 만나는 순간 연산을 중단하고 결과값을 return 하기 때문에 연산이 오래걸리는 조건의 경우에는 최대한 뒤에 배치하는 것이 좋다. 동일한 결과값을 얻기 위해서 더 많은 시간을 사용하는 것은 효율적이지 못하다! 기억하자. Simple conditions first!!

! (not)

! (not) 연산자는 값을 반대 값으로 변환하여 return 해준다.

Control flow

If 조건문

위에서 정리한 여러가지 비교연산자나 논리연산자 등을 통해서 조건에 따라 다른 동작을 실행할 수 있도록 하는 것이 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 의 경우에는 elseblock 안에 있는 코드를 실행한다. 아래처럼 여러 개의 else if 를 사용할 수도 있다.

if ( 조건 1) {
  동작1
} else if ( 조건 2) {
  동작2
} else if ( 조건 3) {
  동작3
} else if ( 조건 4) {
  동작4
} else {
  마지막... 이제 그만!
}

물론 위의 방법은 추천하고 싶지 않다. 여러 개의 else if 를 사용하는 경우에는 switch 를 고려해보자.

Ternary operator

삼항 연산자는 if...else 를 간단하게 표현할 수 있다.

console.log(name === 'cheoljin' ? 'yes' : 'no');

다른 표현식의 일부로서 사용할 수 있기 때문에 유용하다. 다만, 계속 중첩하여 사용하는 경우라면 삼항 연산자가 아닌 ifswitch 를 사용하는 것이 가독성에서도 좋다.

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

breaktrue 값을 가진 case를 만났을 때 해당하는 코드를 실행한 뒤에 block 을 탈출하게 해준다. 만약 위의 코드에서 break가 없다면 true 을 만난 곳부터 이후의 모든 코드가 실행된다. 이것은 우리가 원하지 않는 결과이기 때문에 break 를 꼭 써주자.

default 의 경우에는 모든 casefalse 일 때 실행된다.

While loops

같은 작업을 여러 번 반복 시키고 싶을 때 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 loops

반복문에는 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에도 continuebreak 를 사용할 수 있다. 간단한 예시를 보자.

for (let i = 0; i < 11; i++) {
  if (i % 2 === 1) {
    continue;
  } else {
    console.log(`q1: ${i}`);
  }
}

continuebreak 처럼 block 를 탈출하도록 하는 역할을 하지만 반복문 자체를 탈출하는 break 와는 다르게 해당하는 경우만 탈출하여 반복문을 계속 실행한다. 위의 경우에는 i % 2 === 1 을 만족하는 홀수의 경우에는 즉시 if를 탈출한 후에 다음 반복문을 진행하였다. 그래서 짝수만을 출력할 수 있었다.
( 실제로 짝수만을 출력하고 싶은 경우에는 위의 방법보다 원하는 값만 출력하도록 코드를 작성하는 것이 좋다. 예시를 위해 위처럼 작성하였다.)

for (let i = 0; i < 10; i++) {
  if (i > 8) {
    break;
  } else {
    console.log(`q2: ${i}`);
  }
}

i 가 8보다 큰 경우에는 반복문이 멈추도록 하였다. 위의 예시들처럼 continuebreak 를 통해서 반복문을 더욱 편리하게 제어할 수 있다.

참고자료:
드림코딩 by 엘리

profile
사회에 도움이 되는 것은 꿈, 바로 옆의 도움이 되는 것은 평생 목표인 개발자.

0개의 댓글

관련 채용 정보