생성자처럼 사용할 수 있지만 생성되는 결과물은 예상과는 조금 다를 수 있습니다.
const a = "abc";
const b = new String("abc");
typeof a; // string
typeof b; // object
b instanceof String; // true
new String("abc") 생성자의 결과는 원시 값 "abc"를 감싼 객체 래퍼(Wrapper)입니다.
어떠한 객체가 어떤 네이티브에 속하는지는 Object.prototype.toString()이라는 메서드에 값을 넣어 호출해봄으로써 확인해볼 수 있습니다.
여기서 중요한 것은 우리는 흔히 const a = "abc"를 선언하여 a.length, a.toString같은 메서드를 사용할 수 있습니다.
이것은 해당 메서드를 사용하는 지점에서 자바스크립트(이하 JS) 엔진이 자동으로 해당 원시 값을 박싱(Boxing)하기 때문입니다.
그러면 우리는 처음부터 선언할 때 객체로 선언하는 것이 오히려 낫지 않냐고 생각할 수 있습니다.
혹시라도 수동으로 원시 값을 박싱하려면 Object() 함수를 사용하면 되긴 합니다. (앞에 new 사용 X)
객체 래퍼의 원시 값은 valueOf() 메서드로 추출합니다.
앞서 말했다시피, 확실히 필요해서 쓰는 게 아니라면 생성자는 가급적 쓰지 않는 편이 좋습니다. 이것은 나중에 예기치 않은 오류와 함정에 빠지게 할 수 있습니다.
하지만, 몇몇 생성자는 유용하게 쓰일 때가 있습니다.
Function 생성자는 함수의 인자나 내용을 동적으로 정의해야 하는, 매우 드문 경우에 한해 유용합니다.
정규표현식은 리터럴 형식으로 정의할 것을 적극 권장하고 있습니다. 구문이 쉽고 성능상 이점(JS 엔진이 실행 전 컴파일하고 캐싱)이 있습니다.
그렇지만, RegExp 생성자는 정규 표현식 패턴을 동적으로 정의할 경우 유용하게 쓰일 수 있습니다.
const name = "Jimmy";
const namePattern = new RegExp("\\b(?:" + name + ")+\\b", "ig");
const matches = "...".match(namePattern);
이런 식으로 사용될 수 있으며 이럴 때는 new RegExp("패턴", "플래그") 형식으로 사용합니다.
Date와 Error는 리터럴 형식이 없으므로 다른 네이티브에 비해 더욱 유용합니다.
Date는 흔하게 사용되므로 Error에 대해 설명하자면, 이 Error 객체는 현재의 실행 스택 컨텍스트를 포착하여 객체에 담은 것입니다. 이 컨텍스트에는 함수 호출 스택, Error 객체가 만들어진 줄 번호 등 디버깅에 도움이 될 만한 정보들을 담고 있습니다. 주로, throw 연산자와 함께 사용합니다.
Symbol은 ES6에서 처음 나온, 새로운 원시 값의 타입입니다. 충돌 염려 없이 객체 프로퍼티로 사용 가능한, 특별한 '유일한 값'입니다.
Symbol은 정의시 new를 붙이면 에러가 나는 유일한 네이티브 생성자입니다.
const mySymbol = Symbol("Hi Symbol!");
let obj = {};
obj[mySymbol] = "foobar";
이런 식으로 객체의 프로퍼티로 삽입할 수 있습니다.
내장 네이티브 생성자는 각자의 .prototype 객체를 가집니다.
Function, RegExp, Array의 prototype의 디폴트 값은 빈 함수, 빈 정규식, 빈 배열입니다.