반응형

 내용은 이웅모 님의 모던 "자바스크립트 DeepDive" 책을 보고 정리한 내용입니다. 저작권 보호를 위해 책의 내용은 요약되었습니다.

 

○ 생성자 함수란?

- new 연산자와 함께 호출하여 새로운 객체(인스턴스)를 생성하는 함수

- 생성자 함수 호출시 함수 내의 코드가 실행된다.

- 일반적으로 대문자로 시작한다.

- 생성자 함수 내에서 this 키워드를 사용하여 객체의 속성과 메서드를 정의할 수 있다.

 

 

 

○ 생성자 함수를 사용하는 이유

- 객체 리터럴은 한 번에 하나의 객체만 생성할 수 있지만 생성자 함수를 사용하면 동일한 구조와 동작을 가진 여러 개의 객체를 생성할 수 있다.
- 생성자 함수를 사용하면 객체의 초기화 과정을 분리할 수 있는데 생성자 함수 내에서 객체의 속성을 초기화하고, 생성자 함수 외부에서는 초기화된 객체를 사용할 수 있다.

// 생성자 함수 정의
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 생성자 함수의 프로토타입에 메서드 추가
Person.prototype.sayHello = function() {
  console.log(`안녕하세요, 저는 ${this.name}입니다.`);
};

// 객체 생성
var person1 = new Person("John", 25);
var person2 = new Person("Jane", 30);

// 객체의 속성과 메서드 사용
console.log(person1.name); // "John"
console.log(person2.age); // 30

person1.sayHello(); // "안녕하세요, 저는 John입니다."
person2.sayHello(); // "안녕하세요, 저는 Jane입니다."

 

 

○ 생성자의 인스턴스 생성과정

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

- 암묵적으로 새로운 빈 객체가 생성된다.
- 생성자 함수의 실행 컨텍스트가 생성되고, 빈 객체 즉, 인스턴스는 this에 바인딩한다.

( this 바인딩에 대한 내용은 해당 링크 참조 )

 

2. 인스턴스 초기화

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

 

3. 인스턴스 반환

- 생성자 함수 내부의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 this를 암묵적으로 반환한다.

function Person(name) {
  this.name = name;
  // 인스턴스 속성 설정 등의 처리...
  // return 문이 없음
}

var person = new Person("John");
console.log(person); // Person { name: "John" }

 

- this가 아닌 다른 객체를 명시적으로 반환하면 return 문에 명시한 객체가 반환된다.

function Person(name) {
  this.name = name;
  // 인스턴스 속성 설정 등의 처리...
  return { greeting: "Hello" };
}

var person = new Person("John");
console.log(person); // { greeting: "Hello" }

 

- 명시적으로 원시값을 반환하면 원시값은 무시되고 this가 반환된다.

function Person(name) {
  this.name = name;
  // 인스턴스 속성 설정 등의 처리...
  return "Hello";
}

var person = new Person("John");
console.log(person); // Person { name: "John" }

 

- 생성자함수에서 this가 아닌 다른 값을 반환하는 것은 생성자의 기본동작을 훼손하므로 함수 내부에서 return문은 반드시 생략해야 한다.

 

 

 

 [[Call]] 메서드와 [[Construct]] 메서드

1. [[Call]] 메서드

- 함수 객체에 내장된 메서드로, 일반 함수 호출을 처리한다.
- [[Call]] 메서드는 함수 객체가 호출될 때 호출되며, 함수의 실행을 담당한다.
- 함수 호출 시 this 바인딩, 인수 전달, 스코프 결정 등의 동작을 처리한다.
- 모든 함수 객체는 [[Call]] 메서드를 가지고 있습니다.

 

2. [[Construct]] 메서드

- 생성자 함수로서 호출될 때의 동작을 정의하는 메서드이다.
- 생성자 함수가 new 키워드와 함께 호출될 때, [[Construct]] 메서드가 호출된다.
- [[Construct]] 메서드는 새로운 빈 객체를 생성하고, 이 객체를 생성자 함수의 this로 바인딩한다.
- 생성자 함수 내에서 this를 통해 속성을 초기화하거나 다른 초기화 작업을 수행한다.
- 생성자 함수 내에서 명시적으로 return문을 사용하지 않으면 [[Construct]] 메서드가 암묵적으로 this를 반환한다. 

- 함수의 정의 방식에 따라 함수를 constructor와  non-constructor로 나눈다.

 

ⓐ constructor : 함수선언문, 함수 표현식, 클래스

// 일반 함수 정의 : 함수 선언문, 함수 표현식
function foo() {}
const bar = function () {};
// 프로퍼티 x의 값으로 할당된 것은 일반 함수로 정의된 함수로 이는 메서드롤 인정하지 않는다.
const baz = {
	x: function () {}
}

// 일반 함수로 정의됝 함수만이 constructor다.
new foo(); // → foo {}
new bar(); // → bar {}
new baz.x(); // → x {}

 

 

ⓑ non-constructor : 메서드(ES6 메서드 축약 표현), 화살표 함수

// 화살표 함수 정의
const arrow = () => {};

new arrow(); // TypeError: arrow is not a constructor

// 메서드 정의: ES6의 메서드 축약표현만 메서드롤 인정한다.
const obj = {
  x () {}
};

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

 

 

 

○ 자바스크립트에서 제공하는 빌트인 생성자 함수의 활용

1. 객체 생성

빈 객체, 배열, 날짜 객체 등의 기본적인 객체를 생성해야 할 때 빌트인 생성자 함수를 사용할 수 있다.

var obj = new Object(); // 빈 객체 생성
var arr = new Array(); // 빈 배열 생성
var date = new Date(); // 현재 날짜와 시간을 가지는 날짜 객체 생성

 

2. 데이터 변환

빌트인 생성자 함수를 사용하여 데이터를 특정 타입으로 변환할 수 있다.

var num = new Number("42"); // 문자열을 숫자로 변환
var str = new String(123); // 숫자를 문자열로 변환

 

 

3. 기능 확장

빌트인 생성자 함수를 확장하여 원하는 동작을 구현할 수 있다.

function CustomArray() {
  Array.apply(this, arguments); // Array 생성자 함수를 호출하여 기본 동작을 상속받음
  // 추가적인 동작 구현
}

var customArr = new CustomArray(1, 2, 3);

 

4. 예외 처리

빌트인 생성자 함수를 사용하여 오류 객체를 생성하여 예외 처리에 활용할 수 있다.

try {
  // 오류가 발생할 수 있는 코드
} catch (error) {
  var customError = new Error("Custom error message");
  throw customError;
}

 

 

○ new.target이란?

new.target은 JavaScript에서 ES6부터 지원하는 클래스 또는 생성자 함수 내부에서 사용되는 특별한 메타 프로퍼티이다. 이 프로퍼티는 new 연산자와 함께 생성자 함수로서 호출되면 함수 내부의 new.target은 함수자신을 가리킨다. new 연산자 없이 일반 함수로서 호출된 함수 내부의 new.target은 undefined다.

1. 스코프 세이프 생성자 패턴

- 생성자를 new와 함께 호출하면 this는 새로 생성된 객체를 가리키며 이 객체는 실행한 생성자가 정의하는 타입의 인스턴스가 되므로 instanceof를 사용하면 함수를 호출할 때 new를 사용했는지 확인가능하다.

일반적인 스코프 세이프 생성자 패턴의 예시는 다음과 같다:

function MyConstructor() {
  // new.target을 이용하여 생성자 함수가 직접 호출되었는지 확인
  if (!new.target) {
    throw new Error("MyConstructor must be called with 'new'");
  }

  // 프라이빗 멤버 변수
  var privateVariable = 10;

  // 프라이빗 멤버 메서드
  function privateMethod() {
    console.log(privateVariable);
  }

  // 퍼블릭 멤버 메서드
  this.publicMethod = function() {
    privateMethod();
  };
}

// 객체 생성
var myObject = new MyConstructor();
myObject.publicMethod(); // 출력: 10

// 생성자 함수를 직접 호출할 경우 에러 발생
var myObject2 = MyConstructor(); // Error: MyConstructor must be called with 'new'

 

- Object와 Function 생성자 함수는 new 연산자 없이 호출해도 new 연산자와 함께 호출했을 때와 동일하게 동작한다.

반응형

+ Recent posts