[JavaScript] 딥다이브 / 17장 생성자 함수에 의한 객체 생성

ungnam·2023년 6월 21일
0
post-thumbnail

Object 생성자 함수

new Object()로 빈 객체를 생성하여 반환하며, 빈 객체에 프로퍼티 또는 메서드를 추가하여 객체를 완성할 수 있음
-> 객체 리터럴을 사용하는 방식이 더 간편하기 때문에 잘 사용하지 않음

생성자 함수(constructor) : new 연산자와 함께 호출하여 객체를 생성하는 함수로, 이 때 생성된 객체를 인스턴스라고 부른다.

생성자 함수

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

동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 객체 리터럴 방식의 경우 매번 같은 프로퍼티를 기술해야 하기 때문에 비효율적임
-> 생성자 함수를 통해 마치 템플릿처럼 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있음

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

  1. new 연산자와 함께 함수 호출 -> 생성자 함수로 동작
function Circle(radius) {
  // 1. 암묵적으로 빈 객체가 생성되고 this에 바인딩됨
  console.log(this); // Circle {}
  // 2. this에 바인딩된 인스턴스를 초기화함
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
  // 3. 완성된 인스턴스가 바인딩된 this를 암묵적으로 반환함
}
// 0. new 연산자와 함께 함수 호출 => 생성자 함수로 동작
const circle = new Circle(1);
  1. 인스턴스 생성과 this 바인딩

암묵적으로 빈 객체가 생성되며, 이 빈 객체가 바로 생성자 함수가 생성한 인스턴스다. 그리고 이 인스턴스는 this에 바인딩된다. 생성자 함수 내부의 this가 생성자 함수가 생성할 인스턴스를 가리키는 이유가 바로 이것 때문이다.

  1. 인스턴스 초기화

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

  1. 인스턴스 반환

생성자 함수 내부의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환됨
-> 만약 다른 객체가 반환되는 경우 this 대신 반환문에 명시된 해당 객체로 대체됨
-> 원시 값이 반환되는 경우 무시되고 암묵적으로 this가 반환됨

생성자 함수 내부의 반환문은 생성자 함수의 기본 동작을 훼손하기 때문에 반드시 생략해야 한다.

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

함수는 객체로, 일반 객체가 가지고 있는 내부 슬롯과 메서드뿐만 아니라 함수로서 동작하기 위한 [[Environment]], [[FormalParameter]] 등의 내부 슬롯과 [[Call]], [[Construct]] 등의 내부 메서드도 추가적으로 가지고 있다.

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

호출할 수 없는 객체는 함수가 아니므로, 함수는 반드시 callable해야 하지만, 모든 함수가 반드시 constructor이지는 않다.

  • constructor로 동작할 수 있는 경우: 함수 선언문, 함수 표현식, 클래스
  • non-constructor: 화살표 함수, 메서드(ES6 축약표현)

new 연산자

  • new 연산자와 함께 호출하는 함수는 반드시 constructor이어야 한다.
  • new 연산자 없이 생성자 함수를 호출하면 일반 함수로 호출된다. 이 때 일반 함수로 호출된 생성자 함수 내부의 this는 전역 객체 window를 가리킨다.
function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}
// 일반 함수로 호출
const circle = Circle(5);
console.log(circle); // undefined

console.log(radius); // 5 (window.radius)
console.log(getDiameter()); // 10 (window.getDiameter())

일반 함수와 생성자 함수에 특별한 형식적 차이는 존재하지 않기 때문에 생성자 함수의 경우 첫 문자를 대문자로 기술하는 파스칼 케이스로 명명하여 일반 함수와 구별하는 것이 일반적이다.

new.target

  • new 연산자와 함께 호출하면 함수 내부의 new.target은 함수 자신을 가리킴
  • 일반 함수로 호출하면 함수 내부의 new.targetundefined

new.target을 통해 생성자 함수를 일반 함수로 호출했는지 확인하여 그렇지 않은 경우 new 연산자와 함께 생성자 함수로 재귀 호출할 수 있다.

대부분의 빌트인 함수는 new 연산자와 함께 호출되었는지를 확인한 후 적절한 값을 반환함

  • Object, Function, Array, RegExp: new 연산자 없이 호출해도 new 연산자와 함께 호출했을 때와 동일하게 동작
  • String, Number, Boolean: new 연산자 없이 호출 시 문자열, 숫자, 불리언 값을 반환
  • Date: new 연산자 없이 호출 시 현재 날짜 및 시간을 나타내는 문자열을 반환
  • Promise: new 연산자 없이 호출 시 new Promise()syntactic sugar로서 동작
profile
꾸준함을 잃지 말자.

0개의 댓글