728x90
- 예시
3 * "3" //9 1 + "2" + 1 //121 true + true //2 10 - true //9 const foo = { valueOf: () => 2 } 3 + foo // 5 4 * foo // 8 const bar = { toString: () => " promise is a boy :)" } 1 + bar // "1 promise is a boy :)" 4 * [] // 0 4 * [2] // 8 4 + [2] // "42" 4 + [1, 2] // "41,2" 4 * [1, 2] // NaN "string" ? 4 : 1 // 4 undefined ? 4 : 1 // 1
1. 형 변환 (Type coercion)
명시적 Explicit
- 개발자에 의해 의도적으로 값의 타입을 변환하는 것을 명시적 타입 변환(Explicit coercion) 또는 타입 캐스팅(Type casting)이라 한다.
암묵적 Implicit
- 동적 타입 언어인 자바스크립트는 개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되기도 한다. 이를 암묵적 타입 변환(Implicit coercion) 또는 타입 강제 변환(Type coercion)이라고 한다.
실 사용시?
- 암묵적 형변환을 지양하는 것은 옳지 않다. 명시적 타입 변환보다 암묵적 타입 변환이 가독성 면에서 더 좋을 수도 있다. 중요한 것은 코드를 예측할 수 있어야 한다는 것이다. 동료가 작성한 코드를 정확히 이해할 수 있어야 하고 자신의 코드는 타인에 의해 쉽게 이해될 수 있어야 한다. (코드 가독성과 정확성 둘 다 필요하다)
Why 형 변환?
- JS가 Forgiving Language라서 → Web의 동작을 다루니까 최대한 에러가 발생해서 작동을 멈추는 일을 줄여야 함
- JS는 Type을 지정하지 않는 언어 → C, C++ 등의 몇몇 low level 언어와 달리 JS는 각 데이터 유형을 사용할 때 미리 데이터 타입을 지정하지 않는다.
암묵적 형변환 (Implicit coercion)
- 암묵적 타입 변환은 변수 값을 재할당해서 변경하는 것이 아니라 자바스크립트 엔진이 표현식을 에러없이 평가하기 위해 기존 값을 바탕으로 새로운 타입의 값을 만들어 단 한번 사용하고 버린다.
- 자바스크립트 엔진은 표현식을 평가할 때 문맥, 즉 컨텍스트(Context)에 고려하여 암묵적 타입 변환을 실행한다.
- 암묵적 타입 변환이 발생하면 문자열, 숫자, 불리언과 같은 원시 타입 중 하나로 타입을 자동 변환한다.
- ==는 +처럼 암묵적 형변환을 유발한다. ===를 사용하면 형변환이 방지된다.
Three types of conversion
1. JS의 형변환은 아래 세가지만 존재한다.
- to string
- to boolean
- to number
2. 원시타입과 object에 대한 변환 로직은 다르게 작용하지만, 원시타입과 object 모두 형변환될 수 있다.
to String
String(123) // explicit
123 + '' // implicit
String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown
- + 연산자는 수학적 덧셈말고도 문자열을 연결하는 기능(Concatenation)도 수행한다.
- Symbol의 형변환은 명시적(explicit) 형변환만 가능하다.
to Number
Number('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit
Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123
Number(Symbol('my symbol')) // TypeError is thrown
+Symbol('123') // TypeError is thrown
- 비교연산자들 (>, <, <=,>=)
- 비트연산자들 ( OR|, AND&, XOR^, NOT~)
- 산술 연산자들(- + * / % ). 참고, 이진 연산자 +는 문자열을 만나면 숫자 형변환이 일어나지 않는다.
- 단항연산(unary + operator): 피연산자가 1개인 연산 (++ -- + - ~ ! )
- 증가: ++A, A++
- 감소: −−A, A−−
- 양: +A
- 부정: −A
- 자신의 보완: ~A
- 논리적 부정: !A
- 증가: ++A, A++
- 느슨한 동등연산자 == (incl. !=).
- Symbol은 implicit explicit 어느 방법으로도 number로 형변환할 수 없다. 또한 undefined가 NaN가 되는 것과 달리 Symbol의 경우 TypeError를 발생시킨다.
- null -> 0
- undefined -> NaN
- string을 number로 형변환할 때, 엔진은 먼저 공백(\n, \t)을 제거하고, 남은 문자열이 숫자가 아니면 NaN을 반환한다. 만약 빈 문자열이라면 0을 반환한다.
특수 규칙
- null 또는 undefined에 ==을 적용하면 숫자 변환은 일어나지 않는다. null은 null 또는 undefined에 해당하며 다른 어떤 것과 같지 않다.
null == 0 // false, null is not converted to 0 null == null // true undefined == undefined // true null == undefined // true
- NaN은 그 자체와도 비교가 되지 않는다.
if (value !== value) { console.log("we're dealing with NaN here") }
to Boolean
#1
Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator
#2
// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123
#3
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false
#4
Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true
- 논리적 맥락 혹은 논리연산자(||, &&, !)에 의해 발생한다.
- 변환의 결과는 true 혹은 false 단 두 가지다.
- 빈 primitive type은 false, 빈 object는 true다.
- 사실 모두 Number로 변환된 후 비교된다.
- 즉 == 비교 시 false는 0, true는 1로 변환된 후 비교된다.
- 위의 예시에서 #2의 hello와 123의 경우, 내부적으로는 boolean conversion이 발생하지만 boolean이 아니더라도 기존 피연산자의 값을 반환한다.
- #3의 false 값을 반환하는 경우만 외우는 게 편하다.
- #4에 모든 object, function, Array, Date, user-defined type 등의 경우 true를 반환한다.
- Symbol도 true, 빈 배열이나 오브젝트도 true다.
Object 형변환
- object → 원시값 → 최종타입으로 변환의 단계를 거친다.
- object는 모두 [[ToPrimitive]]를 상속받기 때문에 toString toNumber 로 형변환할 수 있다.
728x90
'Programming Language' 카테고리의 다른 글
JS33 - 06.함수 범위, 블록 범위, 렉시컬(lexical) 범위 (0) | 2021.05.31 |
---|---|
JS33 - 05.== and === and typeof (0) | 2021.05.31 |
JS33 - 03.값과 참조(Value and Reference) (0) | 2021.05.31 |
JS33 - 02.원시타입(Primitive Types) (0) | 2021.05.31 |
JS33 - 01.Callstack콜스택 (+ 실행컨텍스트) (0) | 2021.05.31 |
댓글