- 목표
- 생성자 함수의 인스턴스 생성과정을 알아보자.
- 내부 메서드 [[Call]] 과 [[Construct]]를 알아보고 비교해보자.
- constructor와 non-constructor를 구분해보자.
- 생성자 함수의 인스턴스 생성과정
생성자 함수의 역할은 프로퍼티 구조가 동일한 인스턴스를 생성하기 위한 템플릿(클래스)으로서 동작하여 인스턴스를 생성하는 것과 생성된 인스턴스를 초기화(인스턴스 프로퍼티 추가 및 초기값 할당)하는 것이다.
인스턴스 생성 과정
- 인스턴스 생성과 this 바인딩
- 인스턴스 초기화
- 인스턴스 반환
1. 인스턴스 생성과 this 바인딩
암묵적으로 빈 객체가 생성된다. 이 객체는 완성된 객체는 아니나 생성자 함수가 생성한 인스턴스로 분류된다.
그리고 이 객체는 this에 바인딩 된다.
바인딩은 식별자와 값을 연결하는 과정이다.
function Output(text){
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
console.log(this); // Ouput {}
this.text = text;
this.getTextLength = function() {
return this.text.length;
}
}
2. 인스턴스 초기화
생성자 함수에 기술되어 있는 코드가 한 줄씩 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다.
function Output(text){
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
console.log(this); // Ouput {}
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.text = text;
this.getTextLength = function() {
return this.text.length;
}
}
3. 인스턴스 반환
생성자 함수 내부에서 모든 처리가 끝났을 경우 완성된 인스턴스가 바인딩된 this를 암묵적으로 반환한다.
function Output(text){
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
console.log(this); // Ouput {}
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.text = text;
this.getTextLength = function() {
return this.text.length;
}
// 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}
// 인스턴스 생성. Output 생성자 함수는 암묵적으로 this를 반환한다.
const output = new Output('hello world!!!');
console.log(output); // Output {text:'hello world!!!', getTextLength: f}
만약 this가 아닌 다른 객체를 명시적으로 반환하면 this가 반환되지 못하고 return문에 명시한 객체가 반환된다.
하지만, 명시적으로 원시 값을 반환하면 원시 값 반환은 무시되고 암묵적으로 this가 반환된다.
그렇기에 생성자 함수 내부에서 명시적으로 this 외 다른 값을 반환하는 것은 생성자 함수의 기본 동작을 훼손하기 때문에
생성자 함수 내부에서는 return 문을 반드시 생략해야 한다.
- 내부 메서드 [[Call]]과 [[Construct]]
Call : 함수가 일반 함수로서 호출됐을 때 호출되는 메서드
Construct : 함수가 생성자 함수(new연산자와 함께)로서 호출됐을 때 호출되는 메서드
function test() {}
// 일반적인 함수로서 호출: [[Call]]이 호출됨
test();
// 생성자 함수로서 호출: [[Construct]]가 호출됨
new test();
내부 메서드 [[Call]]을 갖는 함수 객체를 callable(호출할 수 있는 객체 : 함수)이라 하며
내부 메서드 [[Construct]]를 갖는 함수 객체를 constructor(생성자 함수로서 호출할 수 있는 함수),
내부 메서드 [[Construct]]를 갖지 않는 함수 객체를 non-constructor(객체를 생성자 함수로서 호출할 수 없는 함수)라고 부른다.
- constructor와 non-constructor 구분
자바스크립트 엔진은 함수 정의를 평가해 함수 객체를 생성할시 함수의 정의 방식에 따라 생성자형과 비 생성자형을 구분한다.
constructor : 함수 선언문, 함수 표현식, 클래스
//함수 선언문
function test() {
console.log('프로그래밍 시험');
}
//함수 표현식
const test = function() {
console.log('프로그래밍 시험');
}
//class
class Person {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
getAge() {
return `${this.firstName} is ${this.age} years old.`;
}
}
non-constructor : 메서드(ES6 메서드 축약 표현), 화살표 함수
// 메서드 정의
const obj = {
test() {
console.log('프로그래밍 시험');
}
}
//화살표 함수 정의(Arrow function)
const test = () => {
console.log('프로그래밍 시험'):
}
일반 함수로만 호출 가능한 객체 | 일반 함수 or 생성자 함수로 호출 가능한 객체 | |
callable | YES | YES |
non-constructor | YES | NO |
constructor | NO | YES |
❗️주의할점
생성자 함수로 호출될 것이라 기대하고 정의하지 않은 일반함수(callable && constructor)에 new 연산자를 붙여 호출하면 생성자 함수처럼 동작할 수 있다.
🔥 배운점
일반적인 함수와 생성자 함수의 차이가 내부 메서드에서도 각각 [[Call]], [[Construct]] 로 차이가 있음을 알았고,
모든 함수는 calllable 속성을 공유하나, 생성자인지 아닌지 여부에 따라 constructor와 non-constructor 속성으로 나뉘는 것을 알았다.
그리고, new 연산자를 일반함수에 붙이면 생성자 함수가 아님에도 생성자 함수처럼 동작 할수 있음에 주의해야겠다.
- 참고
'모던자바스크립트 Deep Dive' 카테고리의 다른 글
[42장] 비동기 프로그래밍 (1) (1) | 2025.02.14 |
---|---|
[37장] Set 과 Map (1) | 2025.01.24 |
[35장] 스프레드 문 (0) | 2025.01.16 |
[22장] this (3) | 2024.09.10 |
[17장] 생성자 함수에 의한 객체 생성 - 1 (2) | 2024.08.20 |