[Programming] - 모던자바스크립트 17. 생성자 함수에 의한 객체 생성
in Programming on Programming, Modernjavascript
객체를 여러개 생성해야할때 아래와 같은 방식은 매우 비효율적이다.
const circle1 = {
radius: 5,
getDiameter() {
return 2 * this.radius;
}
}
const circle2 = {
radius: 10,
getDiameter() {
return 2 * this.radius;
}
}
...
생성자 함수를 통해 객체를 생성 할 수 있다.
function Circle(radius) {
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
new 키워드 없이 사용하면 일반 함수처럼 동작한다.
this
여기서 this를 알아보자.
this의 의미는 함수 호출 방식에 따라 달라진다.
일반 함수 ⇒ window 객체
function foo() {
console.log(this);
}
foo(); //window
메서드 ⇒ 메서드를 호출한 객체
const obj = { foo };
obj.foo(); //obj
생성자 함수 ⇒ 생성될 인스턴스
const inst = new foo(); // inst
생성자 함수 내부에서 this는 암묵적으로 빈 객체 {}가 생성되어있다. 또한 암묵적으로 this를 반환한다.
여기서 주의할 점은 생성자 함수에 명시적 return이 있으면 문제가 발생될수 있다. 빈 객체 반환 : this반환이 무시된다. 빈 객체가 반환된다. 원시값 반환 : 원시값을 무시하고 this가 정상적으로 반환된다.
내부 메서드
함수 객체는 일반 객체와 같이 내부 슬롯과 내부 메서드를 모두 가지고 있다.
여기에 추가적으로 [[Call]]과 [[Construct]] 2가지 내부 메서드를 가지고있다.
일반 객체와 다르게 함수 객체는 호출이 가능함으로 Call 내부 메서드가 호출된다.
function foo() {}
foo(); // [[Call]]이 호출된다.
new foo(); // [[Construct]]가 호출 된다.
[[Call]] 메서드는 함수 객체라면 무조건 가지고 있다.
하지만 [[Construct]] 메서드는 있는 경우와 없는 경우가 있다.
[[Construct]] 메서드가 없는 경우 생성자 함수로써 동작할 수 없다.
생성자 비-생성자 구분
[[Construct]] 메서드가 없는 경우는 어떤 경우일까?
- [[Construct]] 가 있는 경우 : 함수 선언문, 함수표현식, 클래스(클래스도 함수다)
- [[Construct]] 가 없는 경우 : 메서드(ES6 메서드 축약 표현), 화살표 함수
//함수 선언문
function foo() {}
//함수 표현식
const bar = function() {};
const baz = {
x: function() {}
}; //이런 경우도 x에 일반 함수가 정의되어서 메서드로 인정하지 않는다.
new foo();
new bar();
new baz.x();
//화살표 함수
const arrow = () => {};
new arrow(); //Error
//ES6 메서드 축약 표현
const obj = {
x() {}
};
new obj.x(); //Error
new.target
new.target은 this와 유사하게 모든 함수 내부에서 사용가능한 메서드 프로퍼티이다. (IE는 지원안한다.)
new.target으로 생성자 함수로 호출되었는지 확인이 가능하다.
- new.target이 undefined라면 일반 함수 호출
- new.target이 함수 자신을 가르키면 생성자 함수
아래와 같이 응용이 가능하다.
function Circle(radius) {
if(!new.target) {
return new Circle(radius);
}
this.radius = radius;
this.getDiameter = function () {
return this.radius * 2;
}
};
const circle = Circle(10);//실수로 일반함수로 호출해도 생성자 함수로 대응한다.