# 자바스크립트의 타입
- 자바스크립트의 모든 값에는 타입이 있다.
- 원시 타입:
Number
String
Boolean
Undefined
Null
- 데이터 복사가 일어날 때, 메모리 공간을 새로 확보해 독립적인 값을 저장한다.
- 참조 타입:
Object
( Array
Function
Regex
모두 객체에 포함된다. )
- 데이터 복사가 일어날 때, 값 자체가 아닌 메모리의 주소를 참조한다.
- 해당 주소의 값이 변경되면 함께 변경된다.
let a = 10
const b = a
a = 20
console.log(b)
const a = []
const b = a
a.push('hi')
console,log(b)
# 타입 변환
- 타입은 개발자의 의도에 따라 다른 타입으로 변환될 수 있다. 이렇게 의도적으로 타입을 변환하는 것을
명시적 타입 변환
또는 타입 캐스팅
이라 한다.
- 반대로 개발자의 의도와는 상관없이 표현식 평가 도중 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되는 것을
암묵적 타입 변환
또는 타입 강제 변환
이라 한다.
- 원시 값은 변경 불가능한 값이며 변경할 수 없으며, 타입 변환은 기존 원시 값을 사용해 새로운 원시 값을 생성하는 것이다.
const a = 10
const b = a.toString()
const c = a + ''
a.toString()
console.log(a)
const arr = []
arr.push('10')
console.log(arr)
c
예시의 경우, 자바스크립트 엔진은 원시 값 a
를 바탕으로 새로운 문자 ‘10’을 생성하고, 표현식을 평가한다. 이 때 암묵적으로 생성된 문자열 ‘10’은 a
변수에 재할당 되지 않는다.
- 즉, 암묵적 타입 변환은 표현식 평가를 위한 조치이며 새로운 타입의 값을 만들고 사용한 후 버린다.
a.toString()
a + ''
# 생각
암묵적 타입 변환
은 개발자의 의도가 담기지 않으므로 사용에 주의를 기울여야 한다. 그래서 타입스크립트를 쓰는가보다.. 정확한 타입을 지정하거나 좀 더 의도가 명확하게 명시적 타입 변환
을 사용하면 좀 더 클린한 코드가 될 수 있을 것 같다.
- 딥다이브에서는 암묵적 타입 변환이 더 가독성이 좋은 경우도 있다고 하지만, 개인적으로는 협업 측면에서 보면 메서드를 사용한 좀 더 명시적인 타입 변환이 의도를 파악하기 원활해 좋지 않을까 생각해본다.
# 암묵적 타입 변환
문자열 타입으로 변환
암묵적 타입 변환
중 어떤 원리로 변환하는지 알아보겠다.
- 먼저, 문자열 연결 연산자의 역할은 문자열 값을 만드는 것이다. 따라서 코드의 문맥상 모두 문자열 타입이어야 한다.
'10' + 2
true + '10'
5 * '10'
!0
if (1) { }
`1 + 1 = ${1 + 1}`
- 하지만 특정 경우에는 그대로의 값을 문자열로 변환하지는 않는다.
({}) + ''
Math + ''
[] + ''
[10, 20] + ''
Array + ''
숫자 타입으로 변환의 경우
- 산술 연산자의 피연산자 중에서 숫자 타입이 아닌 것을 숫자 타입으로 암묵적으로 변환한다. 이 때, 숫자 타입으로 변환할 수 없는 경우의 결과는
NaN
이 된다.
- 객체와 값이 들어있는 배열, 그리고 undefined의 경우 변환되지 않아
NaN
이 된다.
+ ''
+ 'string'
+ true
+ false
+ null
+ undefined
+ []
+ {}
+ [10, 20]
불리언 타입으로 변환
- if문이나 for문과 같은 제어문 또는 삼항 연산자의 조건식은 불리언 값, 즉 논리적 참/거짓으로 평가되어야 하는 표현식이다.
false
undefined
null
NaN
‘’(빈 문자열)
은 false로 평가되는 Falsy 값이다.
if ('') console.log('1')
if (true) console.log('2')
if (0) console.log('3')
if ('str') console.log('4')
if (null) console.log('5')
if ('0') console.log('6')
# 명시적 타입 변환
문자열 타입으로 변환
String
생성자 함수를 활용하는 방법
toString()
메서드를 활용하는 방법
- 문자열 연결 연산자(암묵적 타입 변환)를 활용하는 방법
String(1)
String(NaN)
String(true)
(1).toString()
(NaN).toString()
(true).toString()
숫자 타입으로 변환
Number
생성자 함수를 활용하는 방법
parseInt
parseFloat
함수를 사용하는 방법(문자열만 숫자 타입으로 변환 가능)
- 단항 산술 연산자를 이용하는 방법(암묵적 타입 변환)
- 산술 연산자를 이용하는 방법(암묵적 타입 변환)
Number('0')
Number('10.53')
Number(true)
Number(false)
parseInt('0')
parseInt('10.53')
parseInt(true)
+'10.53'
true * 2
false * 1
불리언 타입으로 변환
Boolean
생성자 함수를 활용하는 방법
!
부정 논리 연산자를 두 번 사용하는 방법
Boolean('a')
Boolean('')
Boolean('false')
!!'a'
!!''
# 단축 평가
논리 연산자를 사용한 단축 평가
- 표현식 평가 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을
단축 평가
라 한다.
논리곱 연산자(&&)
또는 논리합 연산자(||)
표현식의 평가 결과는 불리언 값이 아닐 수도 있다. 그저 “언제나 어느 한쪽으로 평가된다".
논리곱 연산자
는 두 개의 값이 모두 true일 때 true의 값을 반환한다.
논리합 연산자
는 두 개의 값 중 하나만 true로 평가되어도 true의 값을 반환한다.
- 아래 예시와 같이 논리합/논리곱 연산자는 피연산자를 타입 변환하지 않고 그대로 반환한다.
'Cat' && 'Dog'
'Cat' || 'Dog'
true || anything
false || anything
true && anything
false && anything
단축 평가의 활용
let message = ''
let value = true
if (value) message = '완료'
if (!value) message = '미완료'
message = value && '완료'
message = value || '미완료'
if (value) message = '완료'
else message = '미완료'
message = value ? '완료' : '미완료'
- 변수의 값이 객체가 아니라
null
또는 undefined
인 경우, 객체로 기대하고 프로퍼티를 참조하면 타입 에러가 발생한다.
- 하지만 위 상황에서 단축 평가를 사용하면 에러가 발생하지 않는다.
const obj = null
const value = obj.value
const value = obj && obj.value
- 함수를 호출할 때, 인수를 전달하지 않으면 매개변수에는
undefined
가 할당된다. 이 때 단축 평가를 사용해 매개변수의 기본값을 설정해 undefined
로 인해 발생할 수 있는 에러를 방지할 수 있다.
function test(str) {
str = str || ''
return str.length
}
test()
function test(str = '') {
return str.length
}
옵셔널 체이닝 연산자(?.
)
- ES11에서 도입되었으며 좌항의 값이
null
또는 undefined
인 경우 undefined
를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
const obj = null
const value = obj?.value
const str = ''
const length = str?.length
null 병합 연산자(??
)
- 옵셔널 체이닝 연산자와 마찬가지로 ES11에서 도입되었다.
- 좌항의 값이
null
또는 undefined
인 경우 우항의 값을 반환하고, 그렇지 않으면 좌항의 값을 반환한다.
- 변수에 기본값을 설정할 때 유용하다.
const str = '' || 'default string'
const str = '' ?? 'default string'
const str = null ?? 'default string'