모던 자바스크립트 Deep Dive - 17장 생성자 함수에 의한 객체 생성

밀루·2023년 10월 23일
0

객체 리터럴 외의 객체 생성 방식에 대해 알아보자.

Object 생성자 함수

// 빈 객체 생성
//new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환
const person = new Object(); 

그러나 Object 생성자 함수를 사용해 객체를 생성하는 것은 특별한 이유가 없다면 유용하지는 xxx..


생성자 함수

생성자 함수란 new 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수를 말한다.

생성자 함수에 의해 생성된 객체인스턴스라 한다.

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

객체 리터럴에 의한 생성 방식은 직관적이고 간편하지만

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

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

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

this

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

함수 호출 방식 this가 가리키는 값 (this 바인딩)
일반 함수로 호출전역 객체
메서드로 호출메서드를 호출한 객체 (마침표 앞의 객체)
생성자 함수로 호출생성자 함수가 (미래에) 생성할 인스턴스

일반 함수와 동일한 방법으로 생성자 함수를 정의하고 new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작한다. (이때 new 연산자와 함께 호출하지 않으면 일반 함수로 동작)

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

생성자 함수의 역할은 인스턴스를 생성(필수)하는 것과 생성된 인스턴스를 초기화(인스턴스 프로퍼티 추가 및 초기값 할당)(옵션)하는 것이다.

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

암묵적으로 빈 객체(인스턴스)가 생성된 후 이 인스턴스는 this에 바인딩 된다 (런타임 이전에 실행)

2. 인스턴스 초기화

(런타임ing) this에 바인딩 되어 있는 인스턴스에 프로퍼티나 메서드를 추가하고 생성자 함수가 인수로 전달 받은 초기값을 인스턴스 프로퍼티에 할당하여 초기화 (개발자가 기술)

3. 인스턴스 반환

생성자 함수 내부의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 this를 암묵적으로 반환
(이때 생성자 함수 내부에서 명시적으로 this가 아닌 다른 값을 반환하는 것은 생성자 함수의 기본 동작을 훼손하므로 생성자 함수 내부에서는 return문을 반드시 생략해야한다)

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

함수로서 동작하기 위해 [[Call]][[Construct]]와 같은 내부 메서드를 가지고 있는데

이때 일반 함수로서 호출되면 [[Call]]이 호출되고, new 연산자와 함께 생성자 함수로서 호출되면 [[Construct]]가 호출된다.

함수는 무조건 callable(호출할 수 있는 객체)이지만 constrcutor(생성자 함수로 호출할 수 있는 함수)일 수도 있고 non-constructor(생성자 함수로 호출할 수 없는 함수)일 수도 있다.

그렇다면 이는 어떻게 구분할까?

constructor와 non-constructor의 구분

constructor와 non-constructor은 함수 정의 방식에 따라 구분된다

  • constructor 함수 - 함수 선언문, 함수 표현식, 클래스(클래스도 함수임)
  • non-constructor 함수 - 메서드(메서드 축약 표현), 화살표 함수
const bar = function () {};

new bar(); // bar {}

const obj = {
	x() {}
};

new obj.x(); // TypeError : obj.x is not constructor

new 연산자

new 연산자와 함께 함수를 호출하면 해당 함수는 생성자 함수로 동작해 내부 메서드 [[Construct]]가 호출된다

그리고 반대로 new 연산자 없이 생성자 함수를 호출하면 일반 함수로 호출되며 메서드 [[Call]]이 호출된다

그런데 생성자 함수로서 호출될 것을 기대하고 정의하지 않은 일반 함수에 new 연산자를 붙여 호출하면 생성자 함수처럼 동작할 수 있기 때문에, 이에 대해 유의하여 일반적으로 생성자 함수는 첫문자를 대문자로 기술하는 파스칼 케이스로 명명하여 구분하는 것이 좋다.

new.target

new.target은 this와 유사하게 constructor인 모든 함수 내부에서 암묵적인 지역 변수와 같이 사용되는 메타 프로퍼티이다

new 연산자와 함께 생성자 함수로서 호출되면 함수 내부의 new.target은 함수 자신을 가리킨다.

하지만 new 연산자 없이 일반 함수로서 호출된 함수 내부의 new.target은 undefined이다.

이 때문에 new.target을 통해 new 연산자와 함께 호출되었는지를 확인할 수 있다.

if (!new.target) {
        throw new Error('new 키워드를 사용해주세요');
}

추가로, Object와 Function 생성자 함수는 new 연산자 없이 호출해도 new 연산자와 함께 호출했을 때와 동일하게 동작하는데, Number, String, Boolean 생성자 함수는 new 연산자 없이 호출하면 문자열, 숫자, 불리언 값을 반환한다. 이를 통헤 데이터 타입을 변환하기도 한다.

const str = String(123);
console.log(str); // '123'
profile
이밀루의 도전

0개의 댓글