# type
자바스크립트는 타입이 없는 (척하는) 언어이다.
단순히 변수선언만 var, let, const를 이용해서 한다.
상황에 알맞게 형변환이 가능하다.
js의 primitive type
boolean
string
number
null
undefined
참고 - number는 최대 2^53-1 => 더 큰 정수를 표현하려면 BigInt Standard built-in object를 사용
Symbol 같은 경우에는 ES6에서 새롭게 추가된 스펙이다.
설명이 길어지므로 여기에서는 제외하고 하단에서 설명한다.
# 이상한 null
자바스크립트에서 null은 조금 이상하다.
typeof null // "object"
null은 자바스크립트를 깊숙하게 건드리지않는 이상 undefined와 차이가 없다고 봐도 된다.
null의 사용은 prototype을 끊을때 외에는 undefined를 사용해도 된다.
someObj.prototype = null;
typeof 연산자를 쓰다보면 function이라는 타입이 있다고 착각할수도 있다.
typeof function(){} // "function"
하지만 단순히 "1급 객체", "호출 가능한 객체"일 뿐이다. 실제로는 object의 하위 타입일뿐이다.
null과 undefined를 제외한 3가지는 primitive wrapper가 존재한다.
단순히 첫글자가 대문자일뿐이다.
Boolean
String
Number
new String('boseok')
# boxing, unboxing
예를 들자면
1 === new Number(1) //false
1 === Number(1) //true
1 == new Number(1) //true
typeof new Number(1) //object
== 연산자는 내부적으로 형변환해서 비교하기때문에 아예 안쓰는 연산자이지만 예를 들기위해서 사용하였음.
여튼 위의 코드를 보면, wrapper 객체로 새롭게 생성한 Number의 객체의 타입은 당연히 숫자가 아니라 객체다.
그렇다면 아래와 같은 코드를 보자.
const one = new Number(1);
const two = 2;
const three = one + two;
console.log(three, typeof three); //3 number
one은 객체고, two는 숫자이다.
객체와 숫자를 + 연산자로 합칠수있나?
콘솔로그를 보면 3이 찍히는걸 확인할 수 있다. 그리고 타입도 숫자이다.
이 말은 자동으로 형변환이 이루어진 것인데, wrapper가 벗겨져서 숫자가 된것이므로, 언박싱이라고 한다.
반대로 숫자가 객체로 변환된다면 그것은 박싱이다.
결론은 타입캐스팅을 자동으로 해준다.
그리고 객체가 아니라 단순히 값이나 리터럴을 사용하면 타입 변환이 더 많이 일어난다.
가능한 정확하게 타입을 변환해주는 것이 최선이다.
참고 - 박싱, 언박싱은 자바에서도 마찬가지다.
# 쉽고 빠른 타입캐스팅
숫자와 문자열 - 빈문자열과 +연산자 사용
'' + 1 === '1'; //true
+'1' === 1; // true
Boolean
!!undefined //false
!!null //false
!!0 //false
!!1 // true
!!'' // false
!!'0' // true
!!'1' // true
undefined, null, 0, '' 은 false처럼 작동한다. - 암묵적 타입변환
if(0) {
//실행될수없음
}
if('') {
//실행될수없음
}
if문과 마찬가지로, &&연산자도 마찬가지다.
0 && someFunction(); //아무일도일어나지않음
# && 연산자의 작동방식
위의 예제를 보면, someFunction을 호출하는 코드가 있는데 함수가 호출되지않는다.
&& 연산자는 앞의 expression을 평가해서, false처럼 작동한다면 && 뒤의 expression은 아예 실행조차하지않는다.
비슷하게 || 연산자는 앞의 expression이 true처럼 작동한다면 || 뒤의 expression은 실행하지않는다.
# Symbol
ES6에 새롭게 추가된 스펙이다
Symbol은 새로운 primitive 타입이며,
기존에 object의 key로는 string only였는데, Symbol도 가능하게되었다.
object의 key는 어떤값을 넣던 string으로 타입캐스팅이 되면서 여러가지 문제점들이 있었는데,
ES6가 등장하면서 Map, Symbol등이 그 이슈들을 굉장히 좋은방법들로 해결해준다.
Symbol은 생성자가 없다. 그래서 함수호출형태로만 사용한다.
new 연산자를 못쓴다는 의미이다. wrapper객체를 생성하는 방법은 있긴하지만(Object(Symbol()))
원래의 심볼 목적인 객체 프로퍼티 키로 쓰려고하는 것에 어긋난다.
파라미터는 description이 유일하다. 어떤 용도인지 간단하게 메모하는정도이다. 값은 디버깅외에는 의미없다.
실제로 같은 desc를 넣고(숫자 1), 심볼을 2개 생성해서 객체의 키로 각각 설정해주고 콘솔로그를 보면,
똑같이 생긴 심볼 2개가 각각 객체 키로 설정되어있다. 내부적으로는 키값이 다른것이다.
s1과 s2를 비교해봐도 마찬가지로 다르다.
매 함수호출마다 다른 심볼들을 생성한다.
const s1 = Symbol(1);
const s2 = Symbol(1);
const obj = {
[s1]: 1,
[s2]: 2
}
console.log(obj); // {Symbol(1): 1, Symbol(1): 2}
s1 === s2; // false