생성자 함수란 new 연산자와 함께 호출하여 객체를 생성하는 함수를 말한다. 생성자 함수에 의해 생성된 객체를 인스턴스라고 한다.
자바스크립트는 Object 생성자 함수 이외에도 String, Number, Boolean, Function, Array, Date, RegExp, Promise 등의 빌트인 생성자 함수를 제공한다.
new Object()
인스턴스 생성과 this 바인딩
암묵적으로 빈 객체가 생성되고, 이 객체가 this에 바인딩된다. 따라서 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
이 처리는 런타임 이전에 실행된다.
인스턴스 초기화
this에 바인딩되어 있는 인스턴스에 프로퍼티나 메소드를 추가하고, 인수로 전달받은 초기값을 인스턴스 프로퍼티에 할당한다.
인스턴스 반환
완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
만약 this가 아닌 다른 객체를 명시적으로 반환하면 this 반환은 무시되고 return 문에 명시한 객체가 반환된다.
function Circle(radius) {
// 1. 인스턴스 생성과 this 바인딩
// 2. 인스턴스 초기화
this.radius = radius;
this.getDiameter = function() {
return 2 * this.radius;
};
// 3. 인스턴스 반환 => 암묵적으로 this 반환
return {}; // 다른 객체를 명시적으로 반환 => this 반환 무시
}
그러나, 명시적으로 원시값을 반환하면 원시값 반환이 무시되고 암묵적으로 this가 반환된다.
생성자 함수 내부에서 명시적으로 this가 아닌 다른 값을 반환하는 것은 생성자 함수의 기본 동작을 훼손한다. 따라서 생성자 함수 내부에서 return 문을 반드시 생략해야 한다.
모든 함수는 호출이 가능해야하므로 [[Call]] 을 가지고 있지만, [[Construct]] 는 생성자 함수여야만 가진다.
// 아래와 같이 일반 함수로 정의된 함수만이 constructor
// 함수 선언문
function foo() {}
// 함수 표현식
const bar = function() {};
const baz = {
x: function() {} // x 값으로 할당된 것은 일반 함수로 정의된 함수 => 메소드 X
};
// non-constructor
// 화살표 함수
const arrow = () => {};
const obj = {
x() {} // ES6 메소드 축약 표현
};
// 생성자 함수
function Circle(radius) {
// new와 함께 호출하지 않았다면 new.target 은 undefined
if (!new.target) {
// new 연산자와 함께 생성자 함수 재귀 호출하여 반환
return new Circle(radius);
}
this.radius = radius;
this.getDiameter = function() {
return 2 * this.radius;
};
}
대부분의 빌트인 생성자 함수는 new 연산자와 함께 호출되었는지 확인한 후 적절한 값을 반환한다. new 연산자 없이 호출해도 new 연산자와 함께 호출했을 때와 동일하게 동작하는 것이다.
하지만 String, Number, Boolean 생성자 함수는 new 연산자 없이 호출하면 객체가 아닌 문자열, 숫자, 불리언 값을 반환한다. 이를 통해 데이터 타입을 변환하기도 한다.
const str = String(123);
console.log(str, typeof str); // 123 string
const num = Number('123');
console.log(num, typeof num); // 123 number
const bool = Boolean('true');
console.log(bool, typeof bool); // true boolean