알랑말랑 암묵적 형변환 말랑말랑 이해하기
TL;DR!
- 위 예시의 결과값이 도출되는 과정을 이해한다.
- 암묵적 형변환을 유도하지 말라
- 암묵적 형변환을 유도하지 마시오
타입스크립트를 사용하면 되지 않나요?
들어가기 전에
자바스크립트는 6가지 원시 타입과 Object
라는 객체 타입, 총 7가지 타입 이 존재한다.
ES2020에서 원시 타입에 bigint 타입이 추가되었기 때문에 이제는 총 8가지 타입이 존재하게 되었다.
기본적으로 암묵적 형변환은 모두 "원시 타입(문자열, 숫자, 불리언)"을 기준으로 하게 된다. 원시타입이 객체타입으로 암묵적 형변환이 되는 케이스는 존재하지 않는다.
암묵적 형변환은 언제 일어나나요?
자바스크립트 엔진은 표현식을 평가할 때 문맥, 즉 컨텍스트(Context)에 고려하여 암묵적 타입 변환을 실행한다.
- 산술 연산자(+-*/)의 경우
+
는 문자열이 우선순위가 더 높으며 나머지 연산은 숫자가 더 우선순위가 높다. - 동치 연산자(==)의 경우 피연산자간의 관계에 따라 정의가 다르다.
동치연산자 한짤로 보기
출처: MDN
동치 연산의 관계를 보면 Object
타입의 경우 ToPrimitive
라는 값이 있다.
이 함수가 암묵적 형변환의 핵심이며, 이 함수를 이해하면 타입 변환의 과정을 이해할 수 있다.
ToPrimitive
는 동치연산 뿐만 아니라 원시값과 비교가 필요한 모든 순간에 동작한다
Symbol.toPrimitive
: A method that converts an object to a corresponding primitive value. Called by the ToPrimitive abstract operation.
설명과 같이 객체의 원시 타입의 값을 반환하는 Symbol.toPrimitive
메서드는 ToPrimitive
추상 명령 에서 사용된다.
input 이 객체이며 toPrimitive 추상 명령이 해당 객체 내에 없다면(input[Symbol.toPrimitive]
) OrdinaryToPrimitive
를 호출하고 있다.
input[Symbol.toPrimitive]
이 메서드는 객체 프로퍼티로 개발자가 직접 넣은 케이스이므로 여기서는 넘어가겠다.
hint
는 어떤 원시 타입을 부를지에 대한 정의로써, 기본 타입이 넘버 타입인 것을 인지하고 넘어가자.
hint
가 string
이면 [toString, valueOf]
이며 number
이면 [valueOf, toString]
순서로 우선권을 가지는 것을 볼 수 있다.
여기서 우선권 이라는 단어를 사용하였는데, 그 이유는 for
문을 통해 apply
하는 순서가 달라지기 때문이다.
원시 타입을 찾았다면(if( typeof result !== "object" && typeof result !== "function" )
) 결과를 반환하고 아니면 무시된다 이는 굉장히 중요한데, 아래에서 예시로 다루겠다.
- 따라서, 타입간 비교에서 암묵적 형변환들은 모두 원시타입으로 변환하기 위한 과정 속에서 일어난다.
예제로 정리하기
한발 더 나아가기
hint
는 언제default
값을 벗어나게 될까?<
,>
혹은-
,*
와 같이 명확한 숫자 비교에선number
가 된다.(+
는 문자열도 포함되므로 제외된다)
Date
객체를 제외한 모든 내장 객체는default
와number
를 동일하게 처리하므로number
로 이해하는게 편하다.- 일반 객체는 Symbol.prototype[@@toPrimitive]를 사용하는 반면 Date 객체는 Date.prototype[@@toPrimitive]를 사용한다.
boolean
타입의hint
는 존재하지 않는다. 모든 객체는true
로 평가되므로string
,number
만 처리하면 된다.[Symbol.toPrimitive]
를 커스텀 할 수 있는가?- 가능하다.
NaN
은 모든 경우에서 같지 않다.NaN == NaN // false
결론
- 타입간 비교에서 암묵적 형변환들은 모두 원시 타입으로 변환하기 위한 과정 속에서
ToPrimitive
추상 명령을 통해 일어난다. ==
연산자와===
연산자의 차이는 무엇인가?- "타입까지 비교 여부" 라고하면 애매하다. "암묵적 형변환을 허용하는가"의 차이가 더 명확한 워딩이다.
- 타입스크립트와
===
연산자를 사용하자.
Ref
- 모던 자바스크립트 Deep-dive: 7장 연산자 추상 연산
- ECMA2020
- 동치 연산 관계
- 추상 명령 코드
- 객체를 원시형으로 변환하기
- "[object Object]"