📜 8장. 제어문
제어문이란?
코드의 실행 흐름을 인위적으로 제어할 수 있는 statement
조건에 따라 코드 블록을 실행(=조건문)하거나, 반복 실행(=반복문)할 때 사용한다.
- 제어문을 사용하면 가독성을 해칠 수 있다는 단점이 있다.
➞ 나중에 공부할
forEach
map
filter
reduce
같은 고차 함수를 사용한 함수형 프로그래밍 기법을 통해 가독성을 좋게 만들 수 있다! 😁✶ 8.1 블록문
블록문이란?
0개 이상의 문을 중괄호로 묶은 것
JS에서는 블록문을 하나의 실행 단위로 취급한다.
- 블록문은 단독으로도 사용할 수 있다.
- 블록문은 언제나 문의 종료를 의미하는 자체 종결성을 갖기 때문에 문의 끝에는 세미콜론을 붙이지 않는다.
✶ 8.2 조건문
조건문이란?
주어진 조건식의 평과 결과에 따라 블록문의 실행을 결정한다.
불리언 값으로 평가될 수 있는 표현식이다.
- 조건문에는
if… else
문과switch
문이 있다.
✦ 8.2.1 if…else 문
let x = 2; let result; if (x % 2) { result = '홀수'; } else { result = '짝수'; } // 삼항 조건 연산자로 바꿔쓸 수 있다. result = x % 2 ? '홀수' : '짝수';
- ‘홀수’, ‘짝수’처럼 두 가지 경우의 수가 아닌 세 가지 경우라면
var kind = num ? (num > 0 ? '양수' : '음수' ) : '영';
이런 식으로 괄호를 묶어서 표현할 수도 있다.
- 조건에 따라 단순히 값을 결정하여 할당한다! ➞ 삼항 조건 연산자 사용
- 아니다. 실행할 내용이 복잡하다 ➞
if…else
문 사용
✦ 8.2.2 switch 문
switch 문의 동작 방식
주어진 표현식을 평가하여 그 값과 일치하는 표현식을 갖는 case 문으로 실행 흐름을 옮긴다.
표현식과 일치하는 case 문이 없다면 실행 순서는 default 문으로 이동한다.
switch (표현식) { case 표현식1: switch 문의 표현식과 표현식1이 일치하면 실행될 문; break; case 표현식2: switch 문의 표현식과 표현식2가 일치하면 실행될 문; break; default: switch 문의 표현식과 일치하는 case 문이 없을 때 실행될 문; }
switch
문의 표현식은 문자열이나 숫자 값인 경우가 많다.
폴스루
break를 사용하지 않으면 코드 블록에서 탈출하지 않는다. 또한 case 문의 표현식과 일치하지 않더라도 실행 흐름이 다음 case 문으로 연이어 이동하게 된다. 이를 폴스루(fall through)라 한다.
그러나 여러 케이스에서 같은 코드를 사용할 경우, 폴스루를 활용해서 하나의 조건으로 사용할 수도 있다.
✶ 8.3 반복문
반복문의 동작 방식
조건식의 평가 결과가 참인 경우 코드 블록을 실행한다.
그 후 조건식을 다시 평가하여 여전히 참인 경우 코드 블록을 실행한다.
조건식이 거짓일 때까지 이를 반복한다.
- 반복문에는
for
while
do...while
문이 있다.
✦ 8.3.1 for 문
for (변수 선언문 또는 할당문; 조건식; 증감식) { 조건식이 참인 경우 반복 실행될 문; } // 선언문, 조건식, 증감식은 생략할 수 있다. let i = 0; for (; i < 100; i *= 2) // 무한 루프 for (;;) { ... }
- 일반적으로 선언문에 흔히 사용하는
let i = 0;
의i
는 ‘iteration’을 뜻한다.
for
문은 중첩 사용할 수 있다.
✦ 8.3.2 while 문
let count = 0; while (count < 3) { console.log(count); count++; } // 무한 루프 while (true) { ... } // 무한 루프에서 탈출하기 while (true) { if (어떤 조건) { break } }
- 조건식을 먼저 평가하고 블록문을 실행한다.
while
문은 반복 횟수가 불명확할 때 주로 사용한다.
✦ 8.3.3 do...while 문
let count = 0; do { console.log(count); count++; } while (count < 3);
- 코드 블록을 먼저 실행하고 조건식을 평가한다.
✶ 8.4 break 문
break
문은 레이블 문, 반복문,switch
문을 탈출한다.
- 그 외에 사용하면 SyntaxError(문법 에러)가 발생한다.
레이블 문이 뭐야?
식별자가 붙은 문을 말한다.
foo: { console.log(1); break foo; console.log(2); } outer: for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { if (i + j === 3) break outer; console.log(`inner [${i}, ${j}]`); } }
- 레이블 문을 탈출하기 위해서는
break foo;
처럼 break 문에 레이블 식별자를 지정한다.
- 중첩 for 문을 탈출할 때 유용하지만, 가독성이 나빠지고 오류 발생률이 높아지기 때문에 권장하지 않는다!
✶ 8.5 continue 문
continue 문이란?
반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동시킨다.
for (let i = 0; i < string.length; i++) { if (string[i] === search) { count++; } } // continue를 사용하면 들여쓰기를 막을 수 있다. for (let i = 0; i < string.length; i++) { if (string[i] !== search) continue; count++; }
📜 9장. 타입 변환과 단축 평가
✶ 9.1 타입 변환이란?
- 개발자가 의도적으로 값의 타입을 변환하는 것을 명시적 타입 변환 또는 타입 캐스팅이라 한다.
- 개발자의 의도와 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환 되는 것을 암묵적 타입 변환 또는 타입 강제 변환이라 한다.
- 타입 변환은 기존 원시 값을 변경하지 않는다. 기존 원시 값을 이용해 새로운 원시 값을 생성하는 것이다!
➞ 명시적 타입 변환과 암묵적 타입 변환 중 더 가독성 높은 것을 사용하도록 하자!
✶ 9.2 암묵적 타입 변환
✦ 9.2.1 문자열 타입으로 변환
- 문자열 연결 연산자인
+
를 사용했을 때, 피연산자 중 문자열 타입이 아닌 것을 문자열로 자동 변환한다.
- 템플릿 리터럴의 표현식 삽입은 표현식의 평과 결과를 문자열 타입으로 암묵적 타입 변환한다.
0 + '' -0 + '' 1 + '' -1 + '' NaN + '' Infinity + '' -Infinity + '' true + '' false + '' null + '' undefined + '' (Symbol()) + '' // 유일하게 에러가 난다. ({}) + '' Math + '' [] + '' [10, 20] + '' (function(){}) + '' Array + '' // 템플릿 리터럴 `1 + 1 = ${1 + 1}`
✦ 9.2.2 숫자 타입으로 변환
- 산술 연산자인
-
*
/
를 사용했을 때, 피연산자 중 숫자 타입이 아닌 것을 숫자로 자동 변환한다.
- 비교 연산자인
<
<=
>
>=
를 사용했을 때, 숫자 타입으로 변환한다.
+
단항 연산자도 숫자 타입이 아니면, 숫자로 자동 변환한다.
1 - '1' 1 * '10' 1 / 'one' // 숫자 타입으로 변환할 수 없다면 NaN이 된다. '1' > 0 +'' +'0' +'1' +'string' // NaN +true +false +null +undefined +Symbol() // 에러가 난다. +{} +[] // 0 +[10. 20] +(function(){})
- 빈 문자열, 빈 배열,
null
,false
는 0으로 변환된다. 그 외 객체, 비지 않은 배열,undefined
는 변환이 되지 않아NaN
으로 된다.
❓ 궁금한 점:
NaN
도 type이 Number인데 그럼 변환은 되는 거 아닌가요?➞ ‘string’과 같은 값이
NaN
로 된 게 아니고, 전체 표현식의 평가 결과 값이 NaN
가 된 것!✦ 9.2.2 불리언 타입으로 변환
- 제어문 또는 삼항 조건 연산자의 조건식은
true
orfalse
로 평가되어야 하는 표현식이다. 따라서 자바스크립트 엔진은 조건식의 평가 결과를 불리언 타입으로 암묵적 타입 변환한다.
false
로 평가되는 Falsy 값- false
- undefined
- null
- 0, -0
- NaN
- ‘’(빈 문자열)
true
로 평가되는 Truthy 값은 Falsy 값을 제외한 모든 값이다.- ‘0’
- {}
- []
✶ 9.3 명시적 타입 변환
- 표준 빌트인 생성자 함수(
String
Number
Boolean
)를 new 연산자 없이 호출
- 빌트인 메서드 사용
- 암묵적 타입 변환 이용
✦ 9.3.1 문자열 타입으로 변환
String
생성자 함수를 new 연산자 없이 호출
Object.prototype.toString
메서드 사용
- 문자열 연결 연산자 이용
// 1. String 생성자 함수 new 연산자 없이 호출 String(1); String(NaN); String(Infinity); String(true); String(false); // 2. Object.prototype.toString 메서드 (1).toString(); (NaN).toString(); (Infinity).toString(); (true).toString(); (false).toString(); // 3. 문자열 연결 연산자 1 + ''; NaN + ''; Infinity + ''; true + ''; false + '';
✦ 9.3.2 숫자 타입으로 변환
Number
생성자 함수를 new 연산자 없이 호출
ParseInt
,ParseFloat
메서드 사용(✅문자열만 가능)
- + 단항 산술 연산자 이용
- * 산술 연산자 이용
// 1. Number 생성자 함수 new 연산자 없이 호출 Number('0'); Number('-1'); Number('10.53'); Number(true); Number(false); // 2. parseInt, parseFloat 함수 사용 parseInt('0'); parseInt('-1'); parseFloat('10.53'); // 3. + 단항 산술 연산자 +'0'; +'-1'; +'10.53'; +true; +false; // 4. * 산술 연산자 '0' * 1; '-1' * 1; '10.53' * 1; true * 1; false * 1;
✦ 9.3.3 불리언 타입으로 변환
Boolean
생성자 함수를 new 연산자 없이 호출
!
부정 논리 연산자를 두 번 사용
// 1. Boolean 생성자 함수 new 연산자 없이 호출 Boolean('x'); Boolean(''); Boolean('false'); Boolean(0); Boolean(1); Boolean(NaN); Boolean(Infinity); Boolean(null); Boolean(undefined); Boolean({}); Boolean([]); // 2. ! 부정 논리 연산자 두 번 사용 !!'x'; !!''; !!'false'; !!0; !!1; !!NaN; !!Infinity; !!null; !!undefined; !!{}; !![];
✶ 9.4 단축 평가
단축 평가란?
논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환하는 것을 말한다.
평가 결과가 확정된 경우 나머지 평가 과정을 생략한다.
✦ 9.4.1 논리 연산자를 사용한 단축 평가
||
혹은&&
연산자 표현식은 언제나 2개의 피연산자 중 어느 한쪽으로 평가된다.
- 따라서 이 연산자 표현식의 평가 결과는 불리언 값이 아닐 수도 있다.
- 단축 평가를 활용해
if
문을 대체할 수 있다.
- 단축 평가를 활용해 객체 프로퍼티 참조 시 에러를 방지할 수 있다.
'Cat' && 'Dog' // 'Dog' 반환 'Cat' || 'Dog' // 'Cat' 반환 true || anything // true 반환 false || anything // anything 반환 true && anything // anything 반환 false && anything // false 반환 let done = true; let message = ''; // if 문을 단축 평가로 대체 if (done) message = '완료'; message = done && '완료'; done = false; if (!done) message = '미완료'; message = done || '완료'; // 객체 참조 시 단축 평가 활용 let elem = null; let value = elem && elem.value;
✦ 9.4.2 옵셔널 체이닝 연산자
?.
를 사용한다.
- ES11에서 도입되었다.
- 좌항의 피연산자가
null
또는undefined
일 경우undefined
를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
&&
연산자와 ?.
연산자의 차이
&&
는 좌항 피연산자가 Falsy 값이면 무조건 좌항 피연산자를 그대로 반환한다.
?.
는 좌항 피연산자가 Falsy 값이라도 null
undefined
가 아닐 경우 우항의 프로퍼티 참조를 이어간다.
✦ 9.4.3 null 병합 연산자
??
를 사용한다.
- ES11에서 도입되었다.
- 좌항의 피연산자가
null
또는undefined
일 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.
- 변수의 기본값을 설정할 때 유용하다.