본 포스팅은 JavaScript의 래퍼 객체(Wrapper Object)를 소개합니다.
래퍼 객체(Wrapper Object)
JavaScript의 특징 중 하나는 동적으로 데이터 타입을 설정하므로 변수를 선언할 때 변수의 데이터 타입을 지정할 필요가 없다는 것이다. JavaScript가 동적으로 데이터 타입을 설정하므로 모든 변수는 선언된 값에 해당하는 데이터 타입을 가지며, 래퍼 객체는 기본 타입(원시 타입)을 객체로 변환하는 역할을 수행한다.
예를 들어, 아래와 같이 문자열 변수를 생성하면 JavaScript는 내부적으로 new String()을 호출하여 기본 타입인 string을 래퍼 객체은 String으로 변환한다.
// 아래와 같이 문자열 변수를 생성하면 기본 타입으로 설정되는 것 같지만
let str = 'JavaScript';
// JavaScipt는 아래와 같이 래퍼 객체로 변환시킨다.
let str = new String('JavaScript');
기본 타입과 래퍼 객체의 차이점은 기본 타입은 값 자체만을 가지고 있고 메서드와 프로퍼티를 가지고 있지 않는다. 하지만 래퍼 객체는 기본 타입을 감싸고 각 타입에 대한 메서드와 프로퍼티를 제공한다.
JavaScript의 기본 타입은 총 7개로 string, number, bigint, boolean, undefined, symbol, null을 제공한다. 래퍼 타입은 null과 undefined를 제외한 5가지 기본 타입 string, number, bigint, boolean, symbol을 래핑하는 객체를 제공한다. 아래 도표는 기본 타입과 매핑되는 래퍼 객체를 보여준다.
기본 타입(Primative Types) | 래퍼 객체(Wrapper Object) |
---|---|
string | String |
number | Number |
bigint | BigInt |
boolean | Boolean |
symbol | Symbol |
본 포스팅은 래퍼 객체 String, Number, Boolean를 예시로 설명한다.
문자열 (String)
String 타입에 대한 래퍼 객체는 String() 생성자 함수로 생성할 수 있다. 이 객체는 문자열을 처리할 수 있는 유용한 프로퍼티와 메서드를 제공한다. 예를 들어, 문자열의 길이를 반환하는 length 프로퍼티와 문자열을 대문자로 변환하는 toUpperCase() 메서드가 있다.
let str = "Hello, World!";
console.log(str.length); // 13
console.log(str.toUpperCase()); // "HELLO, WORLD!"
let strObj = "Hello, World!";
console.log(strObj.length); // 13
console.log(strObj.toUpperCase()); // "HELLO, WORLD!"
숫자 (Number)
Number 타입에 대한 Wrapper Object는 Number() 생성자 함수로 생성할 수 있다. 이 객체는 숫자를 처리하는데 유용한 프로퍼티와 메서드를 제공한다. 예를 들어, 숫자를 고정 소수점으로 표시하는 toFixed() 메서드와 숫자를 문자열로 반환하는 toString() 메서드가 있다.
let num = 123.45;
console.log(num.toFixed(3)); // 123.450
console.log(num.toString()); // "123.45"
let numObj = new Number(123.45);
console.log(numObj.toFixed(3)); // 123.450
console.log(numObj.toString()); // "123.45"
불리언 (boolean)
Boolean 타입에 대한 Wrapper Object는 Boolean() 생성자 함수로 생성할 수 있다. 이 객체는 불리언 값을 처리하는데 유용한 메서드를 제공한다. 예를 들어, Boolean 객체의 원시 값을 반환하는 valueOf() 메서드와 불리언 값을 문자열로 반환하는 toString() 메서드가 있다.
let bool = true;
console.log(bool.valueOf()); // true
console.log(bool.toString()); // "true"
let boolObj = new Boolean('Hello');
console.log(boolObj.valueOf()); // true
console.log(boolObj.toString()); // "true"
가비지 수집기에 의해 회수되는 래퍼 객체
기본 타입과 래퍼 객체의 또 다른 차이점은 기본 타입으로 선언된 변수는 프로퍼티와 메서드를 추가할 수 없다는 것이다. 변수를 기본 타입으로 선언하면 임시적으로 래퍼 객체로 변환하는 것이므로 프로퍼티와 메서드를 추가할 수 없다. 임시적으로 변환한 래퍼 객체를 한 번 사용한 직후 가비지 수집기에 의해 메모리에서 회수되기 때문이다.
아래는 문자열 변수를 기본 타입으로 선언하고 name이라는 프로퍼티를 추가한다.
// 문자열 변수 생성
let str = 'Hello';
// name 프로퍼티 추가
str.name = 'Bob';
// 문자열 변수의 name 프로퍼티 출력
console.log(str.name); // undefined
JavaScript 엔진은 위 코드를 아래와 같이 해석한다. 기본 타입을 임시적으로 래퍼 객체로 변환한다. 따라서, 프로퍼티와 메서드를 추가할 수 없다.
let str = new String('Hello');
new String(str).name = 'Bob';
console.log(new String(str).name);
기본 타입에 프로퍼티와 메서드를 추가하고 싶다면, 명시적으로 래퍼 객체를 생성한다.
// 문자열 변수 생성
let str = new String('Hello');
// name 프로퍼티 추가
str.name = 'Bob';
// 문자열 변수의 name 프로퍼티 출력
console.log(str.name); // "Bob"
변수를 래퍼 객체로 생성하면 프로퍼티와 메서드를 추가할 수 있으므로 기본 타입보다 유용해 보인다. 그러나 래퍼 객체에 프로퍼티와 메서드를 추가하는 상황이 거의 없으며, 프로그래머가 명시적으로 래퍼 객체를 생성하는 경우 메모리 사용량이 늘어나므로 필요한 경우에만 사용하는 것이 좋다.
Conclusion
JavaScript에서 기본 타입과 래퍼 객체는 데이터를 다루는 데 중요한 역할을 수행한다. 기본 타입은 프로퍼티와 메서드를 추가할 수 없지만, 메모리 사용량이 낮다는 특징이 존재하고 래퍼 객체는 프로퍼티와 메서드를 추가할 수 있지만, 메모리 사용량이 기본 타입보다 높다는 특징이 존재한다. 개발자는 변수에 값을 할당할 때, 기본 타입과 래퍼 객체의 특성을 이해하고 적절하게 사용해야 한다.