[8장, 9장] 제어문 ~ 타입 변환과 단축 평가

Sheryl Yun·2022년 6월 8일
0
post-thumbnail

8장

제어문이란 코드의 실행 흐름을 인위적으로 제어하는 문이다.

종류

  1. 조건문 (if-else문, switch문)
  2. 반복문 (for문, while문, do-while문)

함수형 프로그래밍에서는 forEach, map, filter, reduce와 같은 고차 함수를 활용하여 제어문의 사용을 억제하려고 노력한다.

조건문

주어진 조건식의 평가 결과에 따라 코드 블록(블록문)의 실행을 결정하는 문

if-else문과 삼항연산자 비교

if-else문

값처럼 사용할 수 없는 코드 블록이기 때문에 변수에 할당할 수 없다.

삼항연산자

if-else문과 똑같은 역할을 하지만, 값처럼 변수에 할당할 수 있다.

var kind = num ? (num > 0 ? '양수' : '음수') : '영';

if-else문과 switch문 비교

if-else문

조건식이 boolean 값으로 평가되어야 한다.

switch문

조건식이 boolean 값보다 문자열이나 숫자인 경우가 많다.
하지만 이 경우 자바스크립트의 암묵적 타입 변환에 의해 boolean 값으로 바뀌어 평가된다.
논리적 참/거짓(if-else문)보다 다양한 상황(case)에 따라 실행할 코드 블록을 결정할 때 사용한다.

암묵적 타입 변환
조건식에 boolean이 아닌 값이 들어올 경우, 자바스크립트 엔진에 의해 암묵적으로 boolean 값으로 강제 변환되는 것

폴스루(fall through)란?
switch문의 각 case문에 break 키워드를 넣어주지 않아서 해당 코드 블록을 탈출하지 않고 다음 case문을 연이어 실행하는 현상
=> switch문의 각 case문에는 반드시 break 키워드가 있어야 한다.
(default는 모든 case문을 실행하지 않았을 때 실행되고 switch문을 종료하므로 따로 break문이 필요 없음)

일반적으로는 switch문보다 if-else문이 더 좋지만, 조건이 너무 많아서 if-else문이 오히려 가독성이 떨어진다면 switch문을 사용하는 편이 좋다.

반복문

조건문의 평가 결과가 true인 경우 코드 블록을 실행하고, 조건문이 false가 될 때까지 반복하는 문

for문과 while문 비교

for문

반복 횟수가 명확할 때 주로 사용

while문

반복 횟수가 명확하지 않을 때 주로 사용

while문은 조건문이 true이면 무한루프가 되는데, 이를 방지하기 위해
if문으로 탈출 조건을 만들고 if문 내의 break를 통해 while문을 탈출한다.

break문

  • 반복문(for문, while문)switch문을 탈출한다. (if문은 해당 x)
  • 탈출 범위: 이중 for문의 내부 for문에서 break를 실행하면 내부 for문을 탈출하여 외부 for문으로 진입한다.

continue문

반복문의 실행을 continue 실행 지점에서 중단한 후, 반복문의 증감식으로 이동한다.

for (let i = 0; i < array.length; i++) {
	// 조건이 true이면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
    if (arr[i] !== 'l') continue;
    count++; // continue문이 실행되면 이 문은 실행되지 않는다.
}

위의 코드처럼 실행문이 한 줄일 경우에는 continue를 쓰지 않은 다음 코드가 더 간결하다.

for (let i = 0; i < arr.length; i++) {
	// 단순히 'l'이면 카운트를 증가시킨다.
    if (arr[i] === 'l') count++;
}

하지만 실행문이 여러 줄일 경우(count++ 외에 추가로 더 실행할 코드가 있는 경우), continue문을 사용하면 if문 바깥에 추가 실행 코드를 작성할 수 있다.

// continue 사용 x
for (let i = 0; i < array.length; i++) {
	// 'l'이면 카운트를 증가시킨다.
    if (arr[i] === 'l') {
    	count++;
        // 추가 실행 코드
    }
}
// continue 사용
for (let i = 0; i < array.length; i++) {
	// 'l'이 아니면 아래를 실행하지 않고 바로 다음 증감식으로 이동한다.
    if (arr[i] !== 'l') continue;
    
    count++; // continue에 걸리면 여기부터는 실행하지 않는다.
    // 추가 실행 코드
}

9장

타입 변환

값의 타입을 다른 타입으로 변환하는 것

명시적 타입 변환 (= 타입 캐스팅)

개발자가 의도적으로 값의 타입을 변환하는 것

let x = 10;
let str = x.toString();

암묵적 타입 변환 (= 타입 강제 변환)

개발자의 의도와 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되는 것


let x = 10;
let str = x + '';

타입 변환 둘 다 기존 x 변수의 값을 변경하는 것은 아니다.
원시 값은 변경 불가능(immutable)한 값이므로 변경할 수 없다.
타입 변환은 기존의 원시 값을 사용해 다른 타입의 새로운 원시 값을 생성한다.
자바스크립트 엔진은 이렇게 타입 변환된 값은 단 한 번 사용하고 버린다. (= 가비지 콜렉터에 의해 메모리에서 해제)

암묵적 타입 변환

문자열 타입 변환

  • '+' 연산자는 피연산자 중 하나 이상이 문자열이면 표현식의 최종 평가값을 문자열로 반환한다.

숫자 타입 변환

  • 산술 연산 중, 피연산자 중에 하나라도 숫자 타입으로 변환할 수 없는 값이 있다면 표현식의 평가값으로 NaN을 반환한다.
1 * '10' // -> 10
1 / 'one' // -> NaN
  • 앞에 '+'가 붙으면 숫자값으로 암묵적 타입 변환이 일어난다.
+null // -> 0 
+[] // -> 0
+'' // -> 0
+false // -> 0

+undefined // -> NaN
+{} // -> NaN
+[10, 20] // -> NaN

불리언 타입 변환

자바스크립트 엔진은 boolean 값이 아닌 값을 불리언으로 평가할 때 Truthy(참으로 평가되는 값)와 Falsy(거짓으로 평가되는 값)으로 구분한다.
Falsy 외의 모든 값은 Truthy이다.

// Falsy 값 종류
false
undefined
null
0, -0
NaN
'' (빈 문자열)

명시적 타입 변환

문자열 타입으로 변환

  • String() 생성자 함수
  • .toString() 메서드
  • 문자열 연결 연산자 (+ '')

숫자 타입으로 변환

  • Number() 생성자 함수
  • parseInt(), parseFloat() 함수 (=> 문자열에만 가능)
  • '+' 단항 산술 연산자 (예: +true = 1)
  • '*' 산술 연산자 (예: false * 1 = 0)

불리언 타입으로 변환

  • Boolean() 생성자 함수
  • ! 부정 논리 연산자를 2번 사용 (예: !!x = true, !!'' = false)

단축 평가

표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 결과를 생략하는 것
단축 평가를 하는 방법에는 논리 연산자, 옵셔널 체이닝 연산자, null 병합 연산자를 활용하는 방법이 있다.

1. 논리 연산자 활용

종류: 논리곱 연산자(&&)와 논리합 연산자(||)
연산의 반환값으로 논리 연산의 결과를 결정하는 피연산자를 반환

1) 논리곱 연산자 (&&)

'Cat' && 'Dog' // -> "Dog"

&&은 피연산자가 둘 다 참이어야 true를 반환한다.
즉, 앞이 참이어도 뒤가 거짓이면 false 처리가 되기 때문에,
'논리 연산의 결과를 결정하는 피연산자가 에 있다' 고 보고
반환값으로 뒤의 피연산자를 반환한다.

2) 논리합 연산자 (||)

'Cat' || 'Dog' // -> "Cat"

||은 피연산자 중 하나만 참이어도 true를 반환한다.
즉, 앞이 참이면 뒤는 볼 필요없이 전체 연산 결과는 true 처리가 되기 때문에,
'논리 연산의 결과를 결정하는 피연산자가 에 있다' 고 보고
반환값으로 앞의 피연산자를 반환한다.


즉, 단축 평가는 '어느 쪽이 연산의 결과를 결정하는 지에 따라' 다음의 규칙을 따른다. ``` true && anything // -> anything false && anything // -> false

true || anything // -> true
false || anything // -> anything

단축 평가에서 논리 연산자 활용

1. 단축 평가를 사용하면 if문을 대체할 수 있다.

if (done) message = '완료';

message = done && '완료';
if (!done) message = '진행중';

message = done || '진행중';
if (done) message = '완료';
else message = '진행중';

message = done ? '완료' : '진행중';

2. 참조하는 객체가 null이나 undefined일 때, 단축 평가를 사용하면 에러가 발생하지 않는다.

let element = null;
let value = element.value; // TypeError: Cannot read property 'value' of null

위의 기존 코드는 null인 객체에서 property를 참조하려 했기 때문에 에러가 발생했다.
이를 단축 평가를 사용하여 작성하면 다음과 같다.

let element = null;
let value = element && element.value; // null

단축 평가의 논리 연산자 &&을 사용하면, element.value 참조 시 element의 상태인 null을 그대로 출력하고 에러를 발생시키지 않는다.

3. 함수의 매개변수에 기본값을 설정할 때

function getStringLength(str) {
	str = str || ''; // 초기값 설정
    return str.length;
}
console.log(getStringLength()); // 0
console.log(getStringLength('hi')); // 2

위의 코드는 함수 내부에서 매개변수 str의 기본값을 단축 평가의 논리 연산자 ||를 통해 설정하고 있다.
이를 ES6 문법으로 더 간결하게 표현하면 다음과 같다.

function getStringLength(str = '') {
    return str.length;
}
console.log(getStringLength()); // 0
console.log(getStringLength('hi')); // 2

똑같이 에러 없이 결과가 잘 출력되며, 함수 내부의 코드 한 줄이 줄어들었다.

2. 옵셔널 체이닝 연산자 ?. 활용

  • ES11(ECMAScript2020)에서 도입되었다.
  • 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고,
    그렇지 않으면 우항의 프로퍼티를 계속 참조한다.
  • 단축 평가의 논리 연산자 &&을 대체(개선)하였다.

옵셔널 체이닝 연산자가 논리 연산자 &&을 개선했다고 보는 점

논리 연산자 &&은 좌항의 피연산자가 Falsy 값이면 && 뒤를 더 이상 참조하지 않고 좌항 피연산자를 그대로 반환해버린다.

let str = '';
let length = str && str.length;
console.log(length); // '' (우항의 str.length를 참조하지 못한다)

위의 코드에서 빈 문자열의 길이는 0으로 반환해야 의미적으로 더 맞지만, 논리 연산자 &&은 피연산자의 값이 Falsy로 인식되면 그 피연산자를 그대로 반환해버리고 뒤의 연산은 더 이상 진행하지 않는다.

반면 옵셔널 체이닝 연산자는 좌항의 피연산자가 Falsy 값이더라도 null이나 undefined만 아니면 뒤의 연산을 계속 한다.

let str = '';
let length = str?.length;
console.log(length); // 0 (빈 문자열의 길이 반환)

str이 null이나 undefined이면 undefined를 반환하고,
그 외의 경우(빈 문자열, 빈 배열 등)에는 연산자 뒤의 연산을 계속 수행한다.
따라서 위의 코드의 경우 해당 객체의 길이를 반환하려는 원래의 목적대로 연산이 잘 수행되었다.

3. null 병합 연산자 ?? 활용

  • 마찬가지로 ES11(ECMAScript2020)에서 도입되었다.
  • 좌항의 피연산자가 null 또는 undefined이면 우항의 피연산자를 반환하고,
    그렇지 않으면 좌항의 피연산자를 반환한다.
  • 변수에 기본값을 설정할 때 유용하다 => 단축 평가의 논리 연산자 || 대체(개선)
let foo = null ?? 'default string';
console.log(foo); // default string (좌항이 null인 경우 우항의 피연산자 반환)

null 병합 연산자가 논리 연산자 ||을 개선했다고 보는 점

논리 연산자 ||은 좌항의 피연산자가 Falsy 값(빈 문자열, 빈 배열 등)이면 우항의 피연산자를 반환한다. 이때 이 Falsy 값을 기본값으로 사용하려는 의도로 코드를 작성했다면 의도와 다르게 동작하게 된다.

let foo = '' || 'default string';
console.log(foo); // default string

하지만 null 병합 연산자는 좌항의 피연산자가 null이나 undefined만 아니면, Falsy 값이더라도 그대로 좌항의 피연산자를 반환한다. 이렇게 되면 좌항의 피연산자를 변수의 기본값으로 쓸 수 있게 된다.

let foo = '' ?? 'default string';
console.log(foo); // ''
profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글