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

Seongkyun Yu·2020년 12월 7일
0

TIL - Javascript

목록 보기
11/28

기존 블로그에 작성한 내용을 velog로 이전한 글입니다


1. Object 생성자 함수

new Object(); 를 통해 빈 객체를 생성하고 생성된 객체에 프로퍼티와 메소드를 추가하여 사용한다.


2. 생성자 함수

  • C++, Java처럼 프로퍼티 구조가 동일한 객체를 간편하게 생성할 수 있다.

    // 생성자 함수
    function Discount(price) {
      // 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
      this.price = price;
      this.getDiscountPrice = function () {
        return 0.9 * this.price;
      };
    }
    
    // 인스턴스의 생성
    const dprice1 = new Discount(5000);  // 할인전 가격이 5000원인 객체를 생성
    const dprice2 = new Discount(10000); // 할인전 가격이 10000원인 객체를 생성

    new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작한다.


  • 함수는 객체이므로 일반 객체와 동일하게 동작한다.
    함수로서 동작하기 위해 내부 슬롯과 내부 메소드를 추가로 가지고 있다.

    내부 메소드:
    [[Call]]: callable, 호출할 수 있는 객체 (함수)
    [[Construct]]: constructor, 생성자 함수로서 호출할 수 있는 객체 (new)

    모든 함수는 callable하지만, 모두가 constructor는 아니다.


  • Constructor로 인정 받기 위해선 일반 함수 정의로 선언돼야 한다.

    // 일반 함수 정의 (constructor)
    function Normal() {};
    const NormalLiteral = function () {};
    const NormalObjFunc = {
      x: function () {}     // 이렇게 선언되면 메소드가 아니라 일반 함수이다
    }
    
    new Normal(); // OK
    new NormalLiteral(); // OK
    new NormalObjFunc.x(); // OK

    위 예시 이외에 arrow함수나 축약 표현으로 생성된 메소드는 생성자를 갖지 못한다.
    이를 구별하기 위해 생성자 함수는 첫문자를 대문자로 쓰는 파스칼 케이스로 명명한다.


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

    인스턴스(빈 객체)와 this 바인딩 -> 인스턴스 초기화 -> 인스턴스가 바인딩된 this 반환

    function Discount(price) {
      // 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
    
      // 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
      this.price = price;
      this.getDiscountPrice = function () {
        return 0.9 * this.price;
      };
    
      // 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
    }
    
    // 인스턴스 생성. Circle 생성자 함수는 암묵적으로 this를 반환한다.
    const dprice1 = new Discount(5000);



  • new 연산자

    constructor 함수와 함께 사용되면 생성자 함수로 작동한다. 형식상 차이는 없다.

    function Discount(price) {
      this.price = price;
      this.getDiscountPrice = function () {
        return 0.9 * this.price;
      };
    }
    
    const dprice1 = Discount(5000);
    console.log(dprice1);  // undefined



  • new.target

    함수 내부에서 new.target를 사용하면 new 연산자와 함께 함수가 호출되었는지 확인할 수 있다.

    function Discount(price) {
      if (!new.target) {
        // new 연산자와 함께 호출하여 생성된 인스턴스를 반환한다.
        return new Discount(radius);
      }
    
      this.price = price;
      this.getDiscountPrice = function () {
        return 0.9 * this.price;
      };
    }
    
    const dprice = Discount(5000);

    ES6 이전에는 스코프 세이프 생성자 패턴을 이용해야 한다.

    // Scope-Safe Constructor Pattern
    function Discount(price) {
      // 생성자 함수가 new 연산자와 함께 호출되면 함수의 선두에서 빈 객체를 생성하고
      // this에 바인딩한다. 이때 this와 Discount는 프로토타입에 의해 연결된다.
    
      // 이 함수가 new 연산자와 함께 호출되지 않았다면 이 시점의 this는 전역 객체 window를 가리킨다.
      // 즉, this와 Discount는 프로토타입에 의해 연결되지 않는다.
      if (!(this instanceof Discount)) {
        // new 연산자와 함께 호출하여 생성된 인스턴스를 반환한다.
        return new Discount(radius);
      }
    
      this.price = price;
      this.getDiscountPrice = function () {
        return 0.9 * this.price;
      };
    }
    
    const dprice = Discount(5000);

참고자료: poiemaweb.com

profile
FrontEnd Developer

0개의 댓글