Deep Dive 17장 생성자 함수에 의한 객체 생성

@hanminss·2021년 12월 2일
0

Deep Dive

목록 보기
9/16
post-thumbnail

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

1. Object 생성자 함수

  • 생성자 함수에 의해 생성된 객체를 인스턴스라 한다.
  • js는 object 이외에도 String, Number, RegExp, Promise 등의 빌트인 생성자 함수를 제공한다.
  • 객체를 생성하는 방법은 객체 리터럴이 더 편리하여 특별한 이유가 없으면 생성자 함수를 쓸 이유가 없다.

2. 생성자 함수

  • 겍체 리터럴에 의한 객체 생성은 간단하지만 단 하나의 객체만을 생성한다는 단점이 있다.
  • 만일 수십개의 객체를 선언해야 한다면 문제가 크다.
// 생성자 함수를 이용하여 많은 객체를 쉽게 생성할 수 있다.

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

const circle1 = new Circle(5);
const circle2 = new Circle(10);

console.log(circle1.getDiameter());
console.log(circle2.getDiameter());
  • 일반 함수와 동일한 방법으로 생성자 함수를 정의하고 new와 함께 호출하면 해당 함수는 생성자 함수로 동작한다.

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

  • new 연산자와 함께 생성자 함수를 호출하면 js 엔진은 암묵적으로 인스턴스를 생성하고 개발자가 쓴 코드를 기반으로 인스턴스를 초기화 한 후 인스턴트를 반환한다.
  1. 인스턴스 생성과 this 바인딩 : new 연산자를 이용하여 생성자 함수를 호출하면 자바스크립트 엔진은 암묵적으로 인스턴스를 생성한다. 그 후 this와 인스턴스는 바인딩된다.(바인딩 : 식별자와 값을 연결하는 과정) 이 처리는 런타임 이전에 실행된다. (만일 바인딩 되지 않았다면 함수 내 this는 함수가 아닌 global을 가르킨다.)

  2. 초기화 : 생성자 함수에 기술되어 있는 코드가 한 줄씩 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다.

  3. 인스턴스 반환 : 초기화 단계가 끝나면 완성된 인스턴스가 암묵적으로 반환된다. 이때 명시적으로 반환된다면 암묵적 반환은 무시된다. 따라서 return 문은 반드시 생략한다.

[[Call]] 과 [[Construct]]

  • 함수 객체도 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드를 모두 가지면서 함수 객체만을 위한 내부 슬롯과 내부 메서드를 추가로 가지고 있다.
  • 일반 객체는 호출할 수 없지만 함수객체는 호출할 수 있는 이유는 함수 객체는 내부 메서드인 [[Call]]을 가지고 있기 때문이다.
  • 또한 new 연산자와 함께 생성자 함수로서 호출되면 내부 매서드인 [[Construct]] 가 호출된다.
  • 모든 함수 객체는 [[Call]] 메서드를 가지고 있고 이들을 callable이라 한다.
  • [[Construct]] 메서드를 가지지 않은 함수 객체도 있다.(축약표현 메서드와 화살표함수 등) 가진 함수객체를 constructor, 가지지 않은 함수 객체를 non-constructor 라고 부른다.

new 연산자

  • new 연산자와 함께 함수를 호출하면 생성자 함수로 동작한다.
  • new 가 붙어있으면 [[Construct]] 내부 메서드를 호출하는 것이고 아니면 [[Call]] 내부 메서드를 호출하는 것이다.

new.target

  • constructor인 모든 함수 내부에서 암묵적인 지역 변수와 같이 사용되며 메타 프로퍼티라 불린다.
  • 생성자 함수로서 호출되면 함수 내부의 new.target은 함수 자신을 가리킨다.
  • new 연산자 없이 함수가 호출되면 new.target은 undefined 이다.
// new.target을 이용하여 생성자 함수가 그냥 호출되는 것을 막아준다.
function Circle(radius) {
  if (!new.target) {
    return new Circle(radius);
  }
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

0개의 댓글