본문 바로가기
FE/JS

[Modern Javascript Deep Dive] #9 타입 변환과 단축 평가

by aeyong-dev 2024. 2. 6.

9. 1 타입 변환이란? 

명시적 타입 변환(explicit coercion) 또는 타입 캐스팅(type casting): 개발자의 의도로 타입 변환

암묵적 타입 변환(implict coercion) 또는 타입 강제 변환(type coercion): JS 엔진에 의한 암묵적인 타입 변환

 

 앞서 타입에는 원시 타입이 있다고 언급했다. 원시 타입은 변경 불가능한 값이기 때문에 타입 변환을 하면 값이 바뀌는 것이 아니라 새로운 값을 생성해낸다. 이 값은 단 한번 사용되고 버려진다(GC에 의해 처리됨). 

 명시적 타입 변환은 코드에 의도가 분명히 드러나지만 암묵적 타입 변환은 그렇지 않다. 따라서 값을 예측 가능하게 코드를 작성해야한다. 명시적, 암묵적 타입 변환 중 가독성이 더 좋고 이해하기 쉬운(예측가능한) 방법을 사용하면 된다. 타입 변환을 포함한 모든 표현 방법에 정해진 방법은 없다. static하게 개발하는 것 보다 dynamic하게 생각하며 코드를 작성하는 것이 이상적이다. 

 

9. 2 암묵적 타입 변환

 앞서 타입을 공부했을 때 암묵적 타입 변환이 발생하는 경우를 알아보았다. 더 자세히 알아보자. 

9. 2. 1 문자열 타입으로 변환

 1 + '2' 의 결과는 '12'이다. 이처럼 + 연산자는 피연산자 중 하나 이상이 문자열 타입일 경우 문자열 연결 연산을 수행한다. 문자열 연결 연산자로 사용하려면 모든 피연산자가 문자열 타입이어야 한다. 그래서 숫자 타입 1이 문자열 타입 '1'로 강제 타입 변환된 것이다. 단, 심벌 타입은 문자열 타입으로 변환될 수 없기 때문에 에러가 발생한다.

 템플릿 리터럴의 표현식 삽입(백틱, ${} 사용)은 표현식의 평과 결과를 문자열 타입으로 암묵적 타입 변환을 수행한다. 

9. 2. 2 숫자 타입으로 변환

 -, *, / 연산자는 모두 산술 연산자다. 산술 연산자는 숫자 타입의 값을 만드는 것이 목적이므로 피연산자는 숫자 타입으로 암묵적 타입 변환된다. 만약 숫자 타입으로 변환 불가능하다면 수학적 연산이 불가능하므로 NaN을 return한다. 

 비교 연산자는 크기 비교를 통해 불리언 겂을 만드는 것이 목적이다. 크기 비교를 위해 피연산자를 숫자 타입으로 강제 타입 변환한다. 마찬가지로 숫자 타입으로의 변환이 불가능하다면 NaN을 return한다. 

 + 단항 연산자는 기능이 없다고 했는데, 숫자 타입으로 변환할 때도 사용된다. 피연산자가 숫자 타입이라면 기능이 없지만 아니라면 숫자 타입으로 암묵적 타입 변환을 수행한다. 이 때, 객체와 배열(빈 배열 제외), undefined는 NaN이 return된다. 

9. 2. 3 불리언 타입으로 변환

 if문, for문 등의 조건식은 불리언 타입으로 평가되어야 한다. 이 때 조건식의 평가 결과가 불리언 타입이 아니라면 암묵적 타입 변환이 수행된다. 결과가 true라면 truthy값, false라면 falsy값이라 한다. 빈 문자열, null, 0은 falsy이다.

 

9. 3 명시적 타입 변환

 개발자가 의도적으로 타입 변환을 수행하는 방법은 세 가지가 있다. 

  • 표준 빌트인 생성자 함수를 new 연산자 없이 호출
    • 표준 빌트인 생성자 함수: 객체 생성을 위한 함수(이 때 new 연산자와 함께 호출)
  • 표준 빌트인 메서드 사용
    • 기본적으로 제공되는 빌트인 객체의 메서드
  • 암묵적 타입 변환 이용

9. 3. 1 문자열 타입으로 변환

  • String 생성자 함수를 new 연산자 없이 호출
  • Object.prototype.toString 메서드 사용
  • 문자열 연결 연산자 이용 (예: + ''; )

9. 3. 2 숫자 타입으로 변환

  • Number 생성자 함수를 new 연산자 없이 호출
  • parseInt, parseFloat 함수 사용(문자열만 가능)
  • + 단항 산술 연산자 이용
  • * 산술 연산자 이용 (*1)

9. 3. 1 불리언 타입으로 변환

  • Boolean 생성자 함수를 new 연산자 없이 호출
  • 부정 논리 연산자(!) 두 번 사용 (!!'hi')

불리언 타입으로 변환할 때, 빈 객체와 배열은 truthy지만 빈 문자열은 falsy인 것에 주의하자. 

 

9. 4 단축 평가

9. 4. 1 논리 연산자를 이용한 단축 평가

 앞서 논리 연산자는 불리언값이 아닌 값으로 평가될 수 있다고 했다. 

'Hi' && 'Hello' // 'Hello'
'Hi' || 'Hello' // 'Hi'

 && 연산자는 좌변과 우변의 값이 모두 true로 평가될 때만 참이다. 좌변이 불리언 타입으로 암묵적 타입 변환되어 truth로 평가된다면 우변의 값이 true인지 false인지 평가해봐야 연산 결과를 알 수 있다. 따라서 우변의 피연산자가 그대로 return된다. 

 반면 || 연산자는 좌변이 true로 평가된다면 우변을 평가하지 않아도 무조건 true를 return할 것이다. 따라서 좌변의 피연산자가 그대로 return된다. 

 이를 활용하여 if문을 대체할 수 있다. 

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

 객체는 key, value의 쌍으로 구성된 프로퍼티의 집합이다. value를 사용하고자 element.value를 사용했을 때, 만약 element가 null 또는 undefined라면 에러가 발생한다. 이를 방지하기 위해 단축 평가를 사용하기도 한다. 

var elem = null;
var value = elem && elem.value; // returns null

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

 함수에 인수를 전달하지 않으면 undefined가 기본적으로 할당된다. 단축 평가를 통해 기본값을 할당하면 undefined로 인한 에러를 방지할 수 있다. 

function temp(str=''){
	return str.length;
}

9. 4. 2 옵셔널 체이닝 연산자

 ES11에 옵셔널 체이닝(optional chaining) 연산자가 도입되었다. ?.를 사용한다. 좌항이 null 또는 undefined라면 undefined를 return하고, 아니라면 참조를 이어간다. 객체가 존재하는지 확인함으로써 에러를 방지할 수 있다. null, undefined일 때만 undefined를 return하고 좌항이 falsy값일 때는 참조를 이어가는 것에 주의하자. 

9. 4. 3 null 병합 연산자

 ES11에 null 병합(nullish coalsecing) 연산자가 도입되었다. ??를 사용한다. 좌항이 null 또는 undefined일 때 우항을 return하고 아니라면 좌항을 return한다. 변수 기본값 설정에 유용하다. null 병합 연산자가 도입되기 전에는 || 논리 연산자를 사용해 기본값을 설정했다. 하지만 이 방법은 좌항이 falsy값일 때도 우항을 return했다.