SDK JS 모던 딥 다이브 스터디 3주차

민겸·2023년 3월 30일
0

SDK 스터디

목록 보기
3/6

3주차는 제어문(8장)과 타입 변환 및 단축 평가(9장)에 대한 내용이다.

제어문은 블록문을 시작으로 조건문과 반복문에 대한 설명이 나와있고,
타입 변환과 단축 평가는 암묵적, 명시적 타입 변환과 단축 평가의 정의와 논리 연산자, 옵셔널 체이닝 연산자 그리고 null 병합 연산자를 이용한 단축 평가에 대한 설명이 니와있다.

8장(제어문) 요약

{}가 블록 또는 스코프라 불리며 실행 단위로 취급되는 것은 알고 있었지만, 블록문이라고 부르기도 한다는 것을 처음 알게 되었다.

조건문은 예상했듯이 if문과 switch ~ case문이다.

두 조건문의 가장 명확한 차이는 조건식이 있는가라고 생각한다.
if문의 경우, if(조건식)으로 사용하게 되는데 이 조건식은 불리언 값으로 암묵적 변환되는 표현식의 평가 결과가 담긴다.
switch문의 경우, switch(표현식)으로 사용하게 되는데, 이 표현식은 불리언 값으로의 암묵적 변환이 일어나지 않고 case 표현식1과 비교하는 방식으로 다음과 같이 작동한다.

switch("표현식"){
  case "표현식1":
    console.log("switch문의 표현식과 표현식1이 일치하면 실행될 문");
  	break;
  case "표현식2":
    console.log("switch문의 표현식과 표현식2가 일치하면 실행될 문");
    break;
  default "기본값":
    console.log("swtich문의 표현식과 일치하는 것이 없다면 default로 실행될 문");
}

반복문은 for문과 while문이다.

반복문은 조건적으로 반복되는 문이며, 기본적인 구조는 다음과 같다.

for(변수 선언문 또는 할당문; 조건식; 증감식){
  조건식이 참인 경우 반복 실행될 문;
}

실행 순서는 다음과 같다.

  1. 변수 선언 및 할당이 실행된다. 이 부분은 최초에 단 한 번만 실행된다.
  2. 조건식이 실행되면서 평가가 이루어진다.
  3. 평가 결과가 거짓이라면 for문 실행이 종료되고, 참이라면 블록문 { 조건식이 참인 경우 반복 실행될 문 }이 실행된다.
  4. 블록문의 실행이 종료되면 증감식이 실행된다.
  5. 증감식이 종료되면 2.번으로 돌아가며, 3.번에 의해 종료될 때까지 순서대로 실행된다.

간단히, 변수 선언 및 할당 > 조건식(참) > 불록문 > 증감식 > 조건식 순서로 생각하면 될 것 같다.

이 다음으로 딥 다이브 책에 나오는 부분인데, 신기한 걸 발견했다.

for(;;) { ... }가 무한히 실행되는 무한루프라고 되어있다. while(true) { ... } 무한루프는 많이 봤어도 for(;;)는 처음 봤다. MDN에 따르면, 이를 empty문이라고 한다.

while문은 while(조건식) { 반복적으로 실행될 코드 }와 같이 사용한다. 위에서도 언급했듯이, 조건식은 표현식의 결과가 불리언 값이 아니라면 암묵적으로 불리언 값으로 강제 변환된다.

반복문은 break문을 사용해서 원하는 시점에서 탈출할 수 있다. for, while 그리고 제어문인 switch에서 사용한다.

반복문이 중첩되어있는 경우에 내부에서 break를 사용하게 되면 그 즉시 내부 반복문을 탈출하여 외부 반복문을 마저 실행한다. 정확히는 레이블문, 반복문(for, for...in, for..of, while, do..while), switch문의 블록{}을 탈출한다.

잠깐, 레이블문이 뭐야?

레이블문은 breakcontinue와 함께 사용할 수 있는 원하는 식별자로 구문 앞에 레이블을 추가할 수 있고 일반적으로 반복문에 레이블을 붙여 사용한다. 다음과 같이 반복문에 식별자를 붙일 수 있다.

labelName:
for(let i = 0; i < 5; i++){ ... }

레이블문을 활용하면 중첩 반복문의 내부에서의 break 한 번의 사용으로 외부 반복문의 탈출이 가능하다.

outer: for(조건식) {
  inner: for(조건식) {
    break outer;
  }
}

continue문을 사용하면 사용 지점에서 반복문의 실행을 멈추고 증감식으로 실행 흐름을 이동시킨다. continue문 또한 레이블문과 같이 사용할 수 있다.

🚨 주의할 점
레이블문을 사용하면 반복문의 실행 흐름을 임의로 조작할 수 있다는 장점이 있지만, 프로그램의 흐름이 복잡해져서 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문에 일반적으로 권장하지 않는다.

9장(타입 변환과 단축 평가) 요약

자바스크립트의 모든 값은 타입을 가지고 있다. 값을 담을 식별자 또한 타입을 가지고 있다. 가장 위에서 타입 변환을 두 가지로 분류해서 소개했었는데, 가장 먼저 암묵적 타입 변환부터 살펴보자.

8장 요약의 조건식은 불리언 값이 아니라면 불리언 값으로 암묵적인 강제 타입 변환이 이루어진다. 이처럼 자바스크립트 엔진에 의해 개발자의 의도와는 상관없이 코드의 문맥을 고려해 암묵적으로 데이터 타입을 강제 변환할 때가 있다.

암묵적 변환

문자열 타입으로 변환

가장 대표적인 예로 +연산자는 피연산자 중 하나 이상이 문자열이라면 산술 연살자가 아닌 문자열 연결 연산자로 동작한다.

1 + '2' // "12"
0 + '' // "0"
-0 + '' // "0"
1 + '' // "1"
-1 + '' // "-1"
NaN + '' // "NaN"
Infinity + '' // "Infinity"
-Infinity + '' // "-Infinity"
true + '' // "true"
false + '' // "false"
null + '' // "null"
undefined + '' // "undefined"
(Symbol()) + '' // TypeError: Cannot convert a Symbol value to a string
({}) + '' // "[object Object]"
Math + '' // "[object Math]"
[] + '' // ""
[10, 20] + '' // "10,20"
(function(){}) + '' // "function(){}"
Array + '' // "function Array() { [native code] }"

이외에 ES6에서 도입된 템플릿 리터럴을 사용하면 표현식의 결과가 문자열 타입으로 암묵적 변환된다.

숫자 타입으로 변환

산술 연산자인 +, -, *, /는 모두 산술 연산자 표현식을 평가하기 위해 산술 연산자의 피연산자 중에서 숫자 타입이 아닌 피연산자를 숫자 타입으로 암묵적 타입 변환한다.
피연산자를 숫자 타입으로 변환할 수 없는 경우 표현식의 평가 결과는 NaN이 된다.

산술 연산자 뿐만 아니라, 비교 연산자 또한 숫자 타입으로의 변환이 이루어지기도 한다.

"3" > 1 // true

비교 연산자는 불리언 값을 만든다. 크기를 비교하기 위해서는 문맥상 피연산자들을 숫자로 취급되어야 하고 이 때 숫자 타입이 아닌 피연산자는 숫자 타입으로 암묵적 변환이 일어나게 된다.

+ 연산자 같은 경우 단항 연산자로 사용하면 피연산자가 숫자 타입이 아니면 숫자 타입의 값으로 암묵적 변환한다.

+'' // 0
+'0' // 0
+'1' // 1
+'string' // NaN
+true // 1
+false // 0
+null // 0
+undefined // NaN
+Symbol() // TypeError: Cannot convert a Symbol value to a number
+{} // NaN
+[] // 0
+[10, 20] // NaN
+(function(){}) // NaN
'0' * 1; // 0
true * 1; // 1
false * 1; // 0

불리언 타입으로 변환

조건식에서 많이 사용하는 암묵적 불리언 타입 변환이다.
조건식에서 false, undefined, null, 0, -0, NaN, ''은 모두 Falsy(거짓으로 간주되는)값이다. Falsy값을 제외하면 모두 Truthy(참으로 간주되는)값이다.

명시적 타입 변환

명시적으로 타입을 변환하는 것에는 여러 가지 방법이 있다.

  • 표준 빌트인 생성자 함수를 new 연산자 없이 호출하는 방법
  • 빌트인 메서드를 사용하는 방법
  • 암묵적 타입 변환을 이용하는 방법

암묵적 타입 변환을 명시적으로 이용하면 명시적 타입 변환을 하는 것이 된다. 암묵적 타입 변환은 앞에서 살펴보았으니 넘어가기로 한다.

문자열 타입으로 변환

  1. String 생성자 함수new 연산자 없이 호출하는 방법
    String(1); // "1"
    String(NaN); // "NaN"
    String(Infinity); // "Infinity"
    String(true); // "true"
    String(false); // "false"
  2. Object.prototye.toString 메서드를 사용하는 방법
    (1).toString(); // "1"
    (NaN).toString(); // "NaN"
    (Infinity).toString(); // "Infinity"
    (true).toString(); // "true"
    (false).toString(); // "false"

숫자 타입으로 변환

  1. Number 생성자 함수new 연산자 없이 호출하는 방법
    Number('0'); // 0
    Number('-1'); // -1
    Number(true); // 1
    Number(false); // 0
  2. parseInt, parseFloat 함수를 사용하는 방법(문자열에만 적용 가능)
    parseInt('1'); // 1
    parseFloat('10.53'); // 10.53

불리언 타입으로 변환

  1. Boolean 생성자 함수new 연산자 없이 호출하는 방법
    Boolean('a'); // true
    Boolean(''); // false
    Boolean('false'); // true
    Boolean(0); // false
    Boolean(1); // true
    Boolean(NaN); // false
    Boolean(Infinity); // true
    Boolean(null); // false
    Boolean(undefined); // false
    Boolean([]); // true
    Boolean({}); // true
  2. ! 부정 논리 연산자를 두 번 사용하는 방법
    !!'a'; // true
    !!''; // false
    !!'false'; // true
    !!0; // false
    !!1; // true
    !!NaN; // false
    !!Infinity; // true
    !!null; // false
    !!undefined; // false
    !![]; // true
    !!{}; // true

단축 평가

논리합 연산자와 논리곱 연산자를 사용한 표현식은 불리언 값이 아닐 때가 있는데 이 때는 두 피연산자 중 어느 한쪽으로 평가된다.

논리합 연산자와 논리곱 연산자 모두 좌항에서 우항으로 평가가 진행된다.
논리합 연산자는 true 또는 Truthy값을 만나는 순간 그리고 논리곱 연산자는 false 또는 Falsy값을 만나는 순간에 타입 변환하지 않고 피연산자를 반환한다.
이를 단축 평가 short-circuit evaluation라 한다.
단축 평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다.

단축 평가 표현식평가 결과
true ⎮⎮ anythingtrue
false ⎮⎮ anythingtrue
true && anythingtrue
false && anythingtrue

단축 평가는 다음과 같은 상황에서 유용하게 사용된다.

객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때

객체를 가리키기를 기대하는 변수의 값이 객체가 아니라 null 또는 undefined인 경우 객체의 프로퍼티를 참조하면 타입 에러가 발생한다. 단축 평가는 이러한 에러 발생으로 인한 프로그램 강제 종료를 미연에 방지할 수 있다.

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

const obj = null;
let value = obj && obj.value; // null

옵셔널 체이닝 연산자와 null 병합 연산자

ES11(ECMAScript2020)에서 도입된 옵셔널 체이닝 연산자null 병합 연산자는 좌항에 null 또는 undefined가 올 수도 있는 상황에 사용하기 좋은 연산자이다.

옵셔널 체이닝 연산자는 바로 위에서 언급한 논리곱 연산자를 이용한 단축 평가 대신 사용하기 좋다.

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

const obj = null;
let value = obj?.value; // null

null 병합 연산자는 좌항의 피연산자가 null 또는 undefined 뿐만 아니라 Falsy값이 올 때도 우항의 피연산자를 반환하는 논리합 연산자와 비교될 수 있는데, 빈 문자열''이나 0 또한 유요한 값으로 취급해야할 때 null 병합 연산자를 사용하기 좋다.

간단한 예시를 들어보자.

let text = '';

let 논리곱결과 = text || 'Hello world';
console.log(논리곱결과); // Hello world

let 병합결과 = text ?? 'Hello world';
console.log(병합결과); // ''

3주차 스터디 회고

이번 3주차에서 empty문과 label문에 처음 알게 되었고, label문과 break, continue과의 조합 또한 알게 되었다. 나머지 내용들은 어느정도 알고있었지만 복습할 수 있게 되어서 보람이 있었다.
하지만, 스터디 날이 되기 전에 empty문과 label문에 대해 깊이 관심을 가지지 않았어서 발표할 주제가 될만 했는데도 발표할 생각을 하지 못했고 결과적으로 발표를 하지 못했다.

스터디에서는 해당 주차에 학습한 할당량에 대해 발표와 토론을 하는데,

같은 주제를 놓고 이것저것 토론하는 것은 정말 좋은데 나를 포함한 모두가 각자 주제를 명확히 정해서 발표하는 것에 있어서 갈피를 못 잡고 있는 느낌이 든다.

이 문제를 보완하기 위해 스터디 주제와 관련이 없어도 알게 된 것에 대해 공유하는 방식으로 진행하기로 했다.

profile
기술부채상환중...

0개의 댓글