javascript에서 다음과 같은 메소드를 사용한 경험이 있을 것이다.

// 대문자로 변경
const greeting = "hello world!";
greeting.toUpperCase();

// 소수점 표현
const num = 1.4435;
num.toFixed(1);

"hello world!"1.4435 는 Primitive 타입이다. 즉, 객체가 아니기에 가지고 있는 메소드가 없다. 하지만 메소드를 사용할 수 있는 이유가 바로 Boxing 과정이 이루어지기 때문이다.

Boxing

Primitive 타입을 wrapper 객체로 wrapping하는 과정을 말한다. greeting변수를 기준으로 설명하고자 한다.

우선 greeting.toUpperCase()를 실행하게 되면 javascript에서 greeting의 Primitive타입의 Reference타입인 String 객체로 암묵적으로 변환 시킨다. 그리고 String의 prototype 체이닝을 타고 toUpperCase() 메소드를 찾아 실행하게 된다. num 변수도 같은 과정이 일어나서 toFixed(1)를 실행할 수 있게 된다.

주로 명시적으로 하기보다 암묵적인 boxing과정을 이용한다.

Unboxing

반대로 Reference타입의 객체의 Primitive 값을 얻는 과정을 말한다. valueOf()메소드를 이용해서 unboxing을 할 수 있다.

const flag = new Boolean(false);
const flag2 = false;

if(flag === flag2) {
  console.log('성공');
} else {
  console.log('실패');
}
// 실패

console.log(typeof flag); // object
console.log(typeof flag2); // boolean

위 과정에서 ===를 사용하여 비교하게 되면 둘은 같지 않게 나온다. 둘의 타입이 다르기 때문이다. 하지만 valueof()를 통해 unboxing을 한다면 unboxing된 값은 Primitive 타입이기에 비교가 성공하게 된다.

const flag = new Boolean(false);
const flag2 = false;

if(flag.valueOf() === flag2) {
  console.log('성공');
} else {
  console.log('실패');
}
// 성공

추가적으로 조금 이해가 필요한 부분이 있는데 다음의 예시를 보자

console.log(flag === flag2); // false
console.log(flag == flag2); // true

==연산에서는 왜 true가 나올까? 타입 비교가 아닌 값의 비교이고 이 때 내부 슬롯 [[PrimitiveValue]]를 이용하여 비교하게 된다.

primitiveValue.png