- 모든 값에는 타입이 있다. 개발자가 의도적으로 값의 타입을 변환할 수 있는데, 이를 명시적 타입 변환 혹은 타입 캐스팅이라고 한다.
- 타입 변환이란 기존 원시 값을 사용해 다른 타입의 새로운 원시 값을 생성하는 것
var x = 10;
// 명시적 타입 변환
// 숫자 -> 문자열
var str = x.toString();
console.log(typeof str, str); // string 10
// x 변수의 값 변경 x
console.log(typeof x, x); // number 10
- 개발자의 의도에 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 변환됨 -> 암묵적 타입 변환 혹은 타입 강제 변환
var x = 10;
// 암묵적 타입 변환
// 문자열 연결 연산자로 인해 숫자 타압 x를 바탕으로 새로운 문자열 생성함
var str = x + "";
console.log(typeof str, str); // string 10
// x 변수의 값 변경 x
console.log(typeof x, x); // number 10- 위 예제에선 새로운 문자열 '10'을 생성하고 x 변수에 재할당하진 않는다.
- 작성한 코드 내 암묵적 타입 변환이 발생하는지, 발생한다면 어떤 타입의 어떤 값으로 변환되는지 그리고 타입 변환된 값으로 표현식이 어떻게 평가되는지 예측 가능해야 한다.
// 피연산자가 모두 문자열 타입
'10' + 2 = '102'
// 피연산자가 모두 숫자 타입
5 * '10' // 50
// 피연산자 또는 표현식이 불리언 타입
10 // true- 위 예제들처럼 코드의 문맥에 부합하지 않을 때 에러 발생과 암묵적 타입 변환 발생함
1 + "2"; // "12"- 문자열 연결 연산자의 모든 피연산자는 코드 문맥상 모두 문자열 타입이어야 한다.
- ** "+" 연산자는 문자열이 포함된 경우 모든 피연산자를 문자열로 변환하여 연결함. "+" 연산자는 문자열 연결과 덧셈이 둘 다 가능해서, 만약 하나라도 문자열이면 문자열로 연결함.**
- -, *, / 같은 연산자는 숫자 연산을 수행하기 위해 문자열을 숫자로 변환함.
- 자바스크립트 엔진은 표현식을 평가할 때 코드 문맥에 부합하도록 암묵적 타입 변환을 실행함.
// + 연산자
console.log("Age: " + 25); // "Age: 25" (숫자 → 문자열 변환)
console.log("Result: " + true); // "Result: true" (불리언 → 문자열 변환)
console.log("Object: " + {}); // "Object: [object Object]" (객체 → 문자열 변환)
console.log("Array: " + [1, 2, 3]); // "Array: 1,2,3" (배열 → 문자열 변환)
console.log("Null: " + null); // "Null: null" (null → 문자열 변환)
console.log("Undefined: " + undefined); // "Undefined: undefined" (undefined → 문자열 변환)
// 객체 타입
console.log({}.toString()); // "[object Object]"
console.log([1, 2, 3].toString()); // "1,2,3"
console.log(new Date().toString()); // 예: "Mon Feb 26 2024 15:30:00 GMT+0900 (KST)"- 자바스크립트 엔진은 산술 연산자 표현식 평가를 위해 산술 연산자의 피연산자 중 숫자 타입이 아닌 피연산자를 숫자타입으로 암묵적 타입 변환함.
- 피연산자를 숫자 타입으로 변환할 수 없는 경우 == 산술 연산을 수행할 수 없으므로 표현식의 평가 결과는 NaN이 됨.
- "+" 연산자는 피연산자가 숫자 타입이 아닐 경우 암묵적 타입 변환 실시
- 빈 문자열, 빈 배열, null, false => 0, true => 1로 변환
- 객체, 빈 배열이 아닌 배열, undefined => NaN
// Number(): 숫자로 변환할 수 없는 값일 경우
console.log(Number(undefined)); // NaN
console.log(Number({})); // NaN (객체)
console.log(Number([])); // 0 (빈 배열은 예외적으로 0으로 변환)
console.log(Number(["10px"])); // NaN (배열이 숫자로 변환 불가)
console.log(Number(function () {})); // NaN (함수)
// parseInt(): 숫자로 변환할 수 없는 경우
console.log(parseInt("px10")); // NaN (숫자로 시작하지 않으면 변환 불가)- 조건식의 평가 결과를 불리언 타입으로 암묵적 타입 변환함.
- 불리언 타입이 아닌 값을 Truthy 값(참으로 평가되는 값) 또는 Falsy 값(거짓으로 평가되는 값)으로 구분함
false로 평가되는 Falsy 값
- false
- undefined
- null
- 0, -0
- NaN
- 빈 문자열
Falsy 값 이외의 모든 값 == 모두 true로 평가되는 Truthy 값
개발자의 의도에 따라 명시적으로 타입 변환
- 표준 빌트인 생성자 함수(String, Number, Boolean: JS의 기본 제공 함수)를 new 연산자 없이 호출하는 방법
- 빌트인 메서드를 사용하는 방법
- 암묵적 타입 변환을 이용하는 방법
문자열 타입으로 변환:
- String 생성자 함수를 new 연산자 없이 호출하는 방법 // String(value)
console.log(String(123)); // "123"
console.log(String(true)); // "true"
console.log(String(false)); // "false"
console.log(String(null)); // "null"
console.log(String(undefined)); // "undefined"
console.log(String([1, 2, 3])); // "1,2,3"
console.log(String({ key: "value" })); // "[object Object]"
console.log(String(Symbol("sym"))); // "Symbol(sym)" (Symbol은 문자열 변환 가능)- Object.prototype.toString 메서드 사용하는 방법 // .toString()
console.log((123).toString()); // "123"
console.log(true.toString()); // "true"
console.log([1, 2, 3].toString()); // "1,2,3"
console.log({ key: "value" }.toString()); // "[object Object]" (기본적으로 이렇게 변환됨)
// null과 undefined는 .toString()을 직접 호출하면 오류 발생!
console.log(null.toString()); // TypeError 발생
console.log(undefined.toString()); // TypeError 발생- 문자열 연결 연산자를 이용하는 방법 // 템플릿 리터럴 ${value}
console.log(`${123}`); // "123"
console.log(`${true}`); // "true"
console.log(`${null}`); // "null"
console.log(`${undefined}`); // "undefined"
console.log(`${[1, 2, 3]}`); // "1,2,3"
console.log(`${{ key: "value" }}`); // "[object Object]"- Boolean 생성자 함수를 new 연산자 없이 호출: 명확하게 true 또는 false를 반환하는 함수
- ! 부정 논리 연산자를 두 번 사용: 부정 연산자를 두 번 사용하여 불리언 변환
1;
"Cat" && "Dog"; // 'Dog'
2;
"Cat" || "Dog"; // 'Cat'- 논리 연산의 결과를 결정하는 두 번째 피연산자인 "Dog" 반환
- 논리 연산의 결과를 결정하는 첫 번째 피연산자인 "Cat" 반환
=> 이처럼 논리 연산의 결과를 결정하는 피연산자를 타입 변환 없이 그대로 반환함 (단축 평가) 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 과정을 생략함
"?.":
- 좌항의 피연산자가 null 또는 undefined인 경우 undefined 반환
- 아닌 경우 프로퍼티 참조를 이어감
- 객체를 가리키는 변수가 null 또는 undefined임을 기대하고 참조할 때 유용하다
// 객체 프로퍼티 접근 시 사용
let user = null;
console.log(user?.name); // undefined (오류 없이 안전하게 처리됨)
// 중첩된 객체 프로퍼티 접근
let user = {};
console.log(user?.profile?.age); // undefined (안전하게 처리됨)
// 배열 요소 접근
let users = null;
console.log(users?.[0]); // undefined (배열이 null이므로 오류 없이 처리됨)
// 메서드 호출
let user = {};
console.log(user.sayHello?.()); // undefined (오류 없이 안전하게 처리됨)
// 옵셔널 체이닝을 delete 연산자와 함께 사용하면 존재하지 않는 프로퍼티를 삭제하려고 할 때도 안전하게 동작
let user = { name: "Alice" };
delete user?.name; //"name" 프로퍼티 삭제됨
delete user?.profile?.age; // profile이 없어도 오류 발생 X
console.log(user); // {}??
- 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환
- 아닐 경우, 좌항의 피연산자 반환
- 변수에 기본값을 설정할 때 유용함
var foo = null ?? "default string";
console.log(foo); // "default string"