[모던 자바스크립트 딥다이브] 17장 생성자 함수에 의한 객체 생성

Soyeon·2025년 3월 20일
1

Object 생성자 함수

new 연산자와 함께 호출해서 객체를 생성하는 함수

  • 인스턴스(instance): 생성자 함수에 의해 생성된 객체
  • 자바스크립트에는 Object 생성자 함수 이외에도 String, Number, Boolean, Function, Array, Date, RegExp, Promise 등의 빌트인 생성자 함수를 제공한다.

객체 리터럴에 의한 객체 생성 방식의 문제

직관적이고 간편하나, 단 하나의 객체만 생성할 수 있다.

-> 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 매번 같은 프로퍼티를 기술해야 하기 때문에 비효율적임

객체는 프로퍼티를 통해 객체의 상태, 메서드를 통해 객체의 동작을 표현한다. 프로퍼티는 객체마다 프로퍼티 값이 다를 수 있지만, 메서드는 내용이 동일한 경우가 일반적이다.

-> 객체 리터럴로 객체를 생성하는 경우, 프로퍼티의 구조가 동일함에도 불구하고 매번 같은 프로퍼티와 메스드를 기술해야 하낟.


생성자 함수에 의한 객체 생성 방식의 장점

템플릿처럼 생성자 함수를 사용해서 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있다.

// 생성자 함수 Person 선언
function Person(name) {
  this.name = name;
  this.getPersonName = function () {
    return `Hi, My Name is ${this.name}`;
  };
}

// new 연산자와 함께 Person 객체(인스턴스) 생성
const person1 = new Person("Soyeon");
const person2 = new Person("Jisoo");

// 각 Person 객체의 메서드 호출
console.log(person1.getPersonName()); // Hi, My Name is Soyeon
console.log(person2.getPersonName()); // Hi, My Name is Jisoo
  • 자바스크립트의 생성자 함수는 클래스 기반 객체 지향 언어와 다르게, 형식이 정해져 있지 않다.
    • 일반 함수와 동일한 방법으로 생성자 함수를 정의하고
    • new 연산자와 함께 호출하면
      -> 생성자 함수로 동작한다
  • 만약, new 연산자와 함께 생성자 함수를 호출하지 않으면, 일반 함수로 동작한다.

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

생성자 함수의 역할?

프로퍼티 구조가 동일한 인스턴스를 생성하기 위한 템플릿으로서,

인스턴스를 생성 (필수) + 생성된 인스턴스를 초기화 (옵션)

1. 인스턴스 생성과 this 바인딩

  • 암묵적으로 빈 객체가 생성됨
  • 이 빈 객체는 생성자 함수가 생성한 인스턴스
  • 이 빈 객체는 this에 바인딩된다.
    • 바인딩: 식별자와 값을 연결하는 과정
    • this 바인딩: this와 가리킬 객체를 바인딩하는 것
fuction Person(name) {
  // 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
  console.log(this); // Person {}
  
  this.name = name;
  this.getName = function () {
    return `Hi, My Name is ${this.name}`
  }
}

2. 인스턴스 초기화

fuction Person(name) {
  // 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
  
  // 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
  this.name = name;
  this.getName = function () {
    return `Hi, My Name is ${this.name}`
  }
}

3. 인스턴스 반환

fuction Person(name) {
  // 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
  
  // 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
  this.name = name;
  this.getName = function () {
    return `Hi, My Name is ${this.name}`
  }
  
  // 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}

// 인스턴스 생성. Person 생성자 함수는 암묵적으로 this 를 반환한다.
const person = new Person('soyeon');
console.log(person); // Person { name: 'soyeon', getName: f }
  • 생성자 함수 내부에서 명시적으로 this가 아닌 다른 값을 반환하면, 생성자 함수의 기본 동작을 훼손하므로 반드시 생성자 함수 내부에서는 return 문을 생략해야 한다.

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

자바스크립트에서 함수는 객체이지만 일반 객체와 다르다.

-> 일반 객체는 호출 불가능, 함수는 호출 가능

함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드,

함수 객체만을 위한 [[Environment]], [[FormalParameters]] 등의 내부 슬롯과 [[ Call ]], [[ Construct ]] 같은 내부 메서드를 추가로 가지고 있기 때문이다.

  • 함수가 일반 함수로 호출되면
    -> 함수 객체 내부 메서드 [[Call]] 호출
    -> 함수 객체 내부 메서드 [[Construct]] 호출

  • [[Call]] 을 갖는 함수 객체 -> Callable = 호출할 수 있는 객체, 함수

  • [[Construct]] 을 갖는 함수 객체 -> Constructor = 생성자 함수로서 호출할 수 있는 함수

constructor & non-constructor

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

new 연산자

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

  • 함수 객체의 내부 메서드 중 [[Construct]] 가 호출됨
  • 단, 이때 호출하는 함수는 construcotr이어야 한다.

new.target

ES6에 도입되어, new 연산자와 함께 생성자 함수로서 호출되었는지 확인할 수 있다.

// 생성자 함수
function Person(name) {
  // 이 함수가 호출되면, 가장 먼저 new 연산자와 함께 호출된 것인지 확인
  if (!new.target) {
    // new 연산자와 함께 호출된 것이 아니면, 함수 내부에서 재귀로 new 연산자와 함께 Person 생성자 함수를 호출
    return new Person(name);
  }

  this.name = name;
  this.getName = function () {
    return `Hi, My Name is ${this.name}`;
  };
}

// new 연산자 없이 생성자 함수를 호출
const person = Person("soyeon");
console.log(person.getName()); 

스코프 세이프 생성자 패턴

IE와 같은 new.target을 지원하지 않는 브라우저에서 생성자 함수를 확인하는 방법

profile
탄탄한 개발자로 살아남기🗿

0개의 댓글