본문 바로가기

Javascript/모던 자바스크립트 DeepDive

[모던 자바스크립트 Deep Dive] 09 타입 변환과 단축 평가

타입 변환이란?

  • 자바스크립트의 모든 값은 타입이 존재
  • 값의 타입은 개발자의 의도에 따라서 다른 타입으로 변경될 수 있음
  • 개발자가 의도적으로 값의 타입을 변경하는 것을 명시적 타입 변환 explicit coercion 또는 타입 캐스팅 type casting이라고 함
  • 개발자의 의도와 상관 없이 표현식을 평가하는 도중 자바스크립트 엔진에 의해 암묵적으로 타입이 자동으로 변경되는 것을 암묵적 타입 변환 implicit coercion 또는 타입 강제 변환 type coercion이라고 함
  • 중요한 것은 예측 가능한 코드
// 명시적 타입 변환
var x = 10;
var str = x.toString();
console.log(typeof str, str); // string 10

// 변수 x 값이 변경된 것은 아님
console.log(typeof x, x); // number 10
// 암묵적 타입 변환
var x = 10;
var str = x + "";
console.log(typeof str, str); // string 10

// 변수 x 값이 변경된 것은 아님
console.log(typeof x, x); // number 10

암묵적 타입 변환

  • 자바스크립트 엔진은 표현식을 평가할 때, 개발자의 의도와는 상관 없이 코드의 문맥을 고려해 암묵적으로 데이터 타입을 강제 변환할 때가 있음
  • 문자열 타입, 숫자 타입, 불리언 타입으로 변환시킴
  • 불리언 타입
    • 자바스크립트 엔진은 불리언 타입이 아닌 값을 Truthy (참으로 평가되는 값) 또는 Falsy (거짓으로 평가되는 값)으로 구분
    • Falsy로 평가되는 값 (나머지 값은 모두 Truthy)
      • false
      • undefined
      • null
      • 0, -0
      • NaN
      • '' (빈 문자열)
// 피연산자 모두 문자열 타입이어야 하는 문맥
'10' + 2 // '102'
// 피연산자가 모두 숫자 타입이어야 하는 문맥
'5' * 10 // 50
// 피연산자 또는 표현식이 불리언 타입이어야 하는 문맥
!0 // true
if (1) {}
function isFalsy(v) {
  return !v;
}

isFalsy(false); // true
isFalsy(undefined); // true
isFalsy(null); // true
isFalsy(0); // true
isFalsy(NaN); // true
isFalsy(''); // true

명시적 타입 변환

  • 개발자의 의도에 따라 명시적으로 타입을 변경하는 방법
    • 표준 빌트인 생성자 함수(String, Number, Boolean)를 연산자 없이 호출
    • 빌트인 메서드 사용
    • 암묵적 타입 변환

단축 평가

논리 연산자를 사용한 단축 평가

  • 논리합(||) 또는 논리곱(&&) 연산자의 표현식 평가 결과가 불리언이 아닌 점을 이용한 방법
  • 단축 평가 short-circuit evalutation는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 의미
  • 단축 평가를 활용하면 if 문을 대체할 수 있음
  • 객체가 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때
  • 함수 매개변수에 기본 값을 설정할 때
// 논리합(||) 연산자는 첫 번째 피연산자가 연산자 표현식의 평가 결과를 결정할 때, 첫 번째 피연산자를 그대로 반환
"Cat" || "Dog"; // 'Cat'
// 논리곱(&&) 연산자는 두 번째 피연산자가 연산자 표현식의 평가 결과를 결정할 때, 두 번째 피연산자를 그대로 반환
"Cat" && "Dog"; // 'Dog'


// 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환
// 논리합(||) 연산자
'Cat' || 'Dog' // 'Cat'
false || 'Dog' // 'Dog'
'Cat' || false // 'Cat'
// 논리곱(&&) 연산자
'Cat' && 'Dog' // 'Dog'
false && 'Dog' // false
'Cat' && false // false
// 어떤 조건이 Truthy일 떄, &&로 if문 대체 가능
var done = true;
var message = "";

if (done) message = "완료";

// 단축 평가
message = done && "완료";
// 어떤 조건이 Falsy일 떄, ||로 if문 대체 가능
var done = false;
var message = "";

if (done) message = "미완료";

// 단축 평가
message = done || "미완료";
// 참고: 삼항 조건 연산자는 if ... else 대체 가능
var done = true;
var message = "";

if (done) message = "완료";
else message = "미완료";

message = done ? "완료" : "미완료";
// 객체는 key와 value로 구성된 property의 집합
// 객체를 가르키기를 기대하는 변수의 값이 객체가 아닌 null이나 undefined라면 타입 에러 발생
var elem = null;
// var value = elem.value; // TypeError: Cannot read properties of null (reading 'value')

// 단축 평가를 사용하면 에러를 발생시키지 않음
var value = elem && elem.value; // null
function getStringLength(str) {
  str = str || "";
  return str.length;
}

getStringLength("abc"); // 3
getStringLength(""); // 0

// 참고 ES6의 매개변수 기본값 설정
function getStringLengthES6(str = "") {
  return str.length;
}

옵셔널 체이닝 연산자

  • ES11(ECMAScript2020)에서 도입된  옵셔널 체이닝 optional chaing 연산자 ?.는 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어감
var elem = null;

// elem이 null 또는 undefined이면 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어감
var value1 = elem?.value;
console.log(value1); // undefined

// 옵셔널 체이닝 연산자 ?.가 도입되기 이전에는 논리연산자 &&를 사용한 단축 평가를 통해 null 또는 undefined를 확인
var value2 = elem && elem.value;
console.log(value2); // null

// 차이점

var str = "";

// 옵셔널 체이닝 연산자 ?.는 좌항 피연산자가 Falsy로 평가되는 값이라도 null undefined가 아니면 우항의 프로퍼티 참조 이어감
var value1 = str?.length;
console.log(value1); // 0

// 논리연산자 &&는 좌항 피연산자가 Falsy로 평가되는 값이면 좌항 피연산자를 그대로 반환
var value2 = str && str.length;
console.log(value2); // ''

null 병합 연산자

  • ES11(ECMAScript2020)에서 도입된 null 병합 nullish coalescing 연산자 ?? 는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환
  • null  병합 연산자는 ?? 변수에 기본값을 설정할 때 유용
var foo = null ?? "default value";
console.log(foo); // 'defalut value'

// null 병합 연산자 ?? 는 좌항이 Falsy 값이라도 null 또는 undefined 값이 아니면 좌항의 피연산자 값을 반환
var value1 = "" ?? "default string";
console.log(value1); // ''

//  null 병합 연산자 ??가 도입되기 이전에는 논리연산자 ||를 사용한 단축 평가를 통해 변수에 기본값을 설정
// 좌항의 피연산자가 Falsy 값이면 우항 피연산자 값을 반환
var value2 = "" ?? "default string";
console.log(value2); // 'default string