17. 생성자 함수에 의한 객체 생성

heyhey·2023년 7월 24일
0
post-thumbnail

중괄호를 직접 열어 사용하는 객체 리터럴 방식 ({}) 이외에도 객체를 생성하는 방법을 여러가지이다.

17.1 Object 생성자 함수

const person = new Object();
person.name = "lee";
person.sayHello = function () {
  console.log("hello");
};
person; // {name:'lee',sayHello: f }

new 연산자와 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환한다.
생성자 함수에 의해 생성된 객체를 인스턴스 라고 한다.

JS에는 String, Number. Boolean, Function, Array, Date. RegExp 등의 빌트인 생성자 함수를 제공한다.

  • String을 사용하더라도 string이 아닌 object 타입이다.

17.2 생성자 함수

객체 리터럴로 생성하면 직관적으로 편하다. 하지만, 생성을 단 하나의 객체만 생성하기 때문에 비효율적일 수 있다.

이럴 때 사용하는 것이 생성자 함수이다. 위에서는 그저 Object를 만들었지만
프로퍼티 구조가 동일한 복잡한 객체 여러개를 생성할 때 유리하다.

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}
const circle = new Circle(5);

this는 객체 자신의 프로퍼티나 메서드를 참조하기 위한 참조변수 이다.
this는 함수 호출 방식에 따라 동적으로 변동된다.

  • 일반 함수로서 호출 => 전역 객체
  • 메서드로서 호출 => 메서드를 호출한 객체 (마침표 앞 객체)
  • 생성자 함수로 호출 => 생성자 함수가 생성할 인스턴스
const bircle = Circle(3);
bircle; // undefined
radius; // 3 ???

new 연산자 없이 함수를 호출하면 일반 함수로 동작한다.
this.radius 를 할당을 해줬기 때문에 여기서의 this는 전역 객체를 가리킨다.

생성자 함수의 인스턴스 생성 과정

생성자 함수의 역할은 인스턴스를 생성하는 것과 생성된 인스턴스를 초기화하는 것이다.
new 연산자와 함께 호출하면, 암묵적으로 인스턴스를 생성하고 반환해준다.

1. 인스턴스 생성과 this 바인딩
암묵적으로 빈 객체가 생성된다. 이 빈 객체가 this에 바인딩된다.

2. 인스턴스 초기화
this에 바인딩된 인스턴스를 초기화한다.
메서드를 추가하거나 프로퍼티의 값을 할당할 수 있다.

3. 인스턴스 반환
생성자 함수 내부의 처리가 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
다른 객체를 return하면 암묵적 this 반환이 무시되어버리니 조심.
하지만 원시값을 return 하면 this 반환이 된다. (? 어려운 js 세계..)

function Circle(radius) {
  // 1. 암묵적으로 빈 객체가 생성되고 this에 바인딩된다.
  // 2. this 에 바인딩된 인스턴스를 초기화한다.
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
  // 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}

내부 메서드 [[Call]][[Construct]]

함수가 일반 함수로 호출되면 [[Call]]이 호출되고
함수가 new 연산자와 함게 호출되면 [[Construct]]가 호출된다.

모든 함수가 생성자 함수로서 호출할 수 있는 것은 아니다.
생성자 함수로 호출할 수 있는 것은 constructor 이라 불린다. (<-> non-constructor)

  • constructor : 함수 선언문, 함수 표현식, 클래스
  • non-constructor : 매서드, 화살표 함수

new 연산자

new 연산자를 이용하는 것은 constructor 이여야 한다.
new 와 함께 쓰면 this가 함수가 생성하는 인스턴스가 되고,
new 없이 일반 함수로 호출하면 this는 전역 객체 window 를 가리킨다.

new.target

new.target은 this와 유사하게 constructor 인 모든 함수에서 암묵적인 지역 변수와 같이 사용된다.
new 연산자와 함께 생성자 함수로서 호출되면, new.taget은 함수 자신을 가리킨다.
만일 new 연산자가 없이 일반 함수로 호출되면 new.target은 undefined가 된다.

function Circle(radius){
  if (!new.taget){
    return new Circle(radius)
  }
  this.redius = radius
}

이렇게 사용하면 new 연산자로 호출하지 않아도 재귀 함수를 통해 생성자 함수로서 호출이 가능하다.

profile
주경야독

1개의 댓글

comment-user-thumbnail
2023년 7월 24일

공감하며 읽었습니다. 좋은 글 감사드립니다.

답글 달기