17.1 Object 생성자 함수
- new Object() // 빈 객체
- 생성자 함수: new 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수
- 인스턴스: 생성자 함수에 의해 생성된 객체
- 빌트인 생성자 함수; String, Number, Boolean, Function, Array, Date, RegExp, Promise, ...
- 객체 리터럴 사용하는 것이 더 편함
17.2 생성자 함수
- 객체 리터럴에 의한 객체 생성 방식의 문제점
- 단 하나의 객체만 생성함
- 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 매번 같은 프로퍼티 기술 => 비효율적
- 객체는 프로퍼티를 통해 객체 고유의 상태 (state) 표현
- 메서드를 통해 상태 데이터인 프로퍼티를 참조하고 조작하는 동작 (behavior) 표현
- 생성자 함수에 의한 객체 생성 방식의 장점
- 객체(인스턴스)를 생성하기 위한 템플릿(클래스)처럼 프로퍼티 구조가 동일한 객체 여러 개 간편 생성 가능
- 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킴
- this: 객체 자신의 프로퍼티나 메서드를 참조하기 위한 self-reference variable (자기 참조 변수)
- this가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 따라 동적으로 결정됨
- 일반 함수로서 호출 => this는 전역 객체
- 메서드로서 호출 => this는 메서드를 호출한 객체(마침표 앞의 객체)
- 생성자 함수로서 호출 => this는 생성자 함수가 (미래에) 생성할 인스턴스
- 생성자 함수는 객체(인스턴스)를 생성하는 함수
- 생성자 함수는 형식이 정해져 있지 않고 일반 함수처럼 정의하고
new 연산자로 호출 시 생성자 함수로 동작 (new 연산자로 호출하지 않고 그냥 호출 시 => 일반 함수로 동작)
- 생성자 함수의 인스턴스 생성 과정
- 생성자 함수 역할: 프로퍼티 구조가 동일한 인스턴스를 생성하기 위한 템플릿으로서 동작하여 인스턴스 생성,
생성된 인스턴스를 초기화 (인스턴스 프로퍼티 추가 및 초기값 할당)
- 인스턴스 생성은 필수, 생성된 인스턴스 초기화는 옵션
- 생성자 함수 몸체 내부에 인스턴스를 생성하고 반환하는 코드는 없음
- JS 엔진은 암묵적인 처리를 통해 인스턴스 생성, 초기화, 반환
- 인스턴스 생성과 this 바인딩
- 암묵적으로 빈 객체가 생성됨 (생성자 함수가 생성한 인스턴스)
- 암묵적으로 생성된 인스턴스(빈 객체)는 this에 바인딩됨
- 함수 몸체 내부 평가할 때 생성됨
- 인스턴스 초기화
- 함수 몸체 내부 런타임 때 this에 바인딩되어 있는 인스턴스 초기화
- 개발자가 기술
- 인스턴스 반환
- 함수 몸체 내부 런타임 과정 모두 끝나면 바인딩된 this가 암묵적으로 반환됨
- 만약 this가 아닌 다른 객체를 명시적으로 반환하면 this가 반환되지 못하고 명시한 객체가 반환됨
- 하지만 명시적으로 원시 값을 반환하면 원시 값 반환은 무시되고 암묵적으로 this가 반환됨
- 생성자 함수 내부에서 return 문은 반드시 생략
- 내부 메서드 [[Call]]과 [[Construct]]
- 함수는 객체이므로 일반 객체 (ordinary object)와 동일하게 동작 가능
- 함수는 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드 모두 가지고 있음
- 함수는 객체이므로 프로퍼티, 메서드 소유 가능
- 함수는 객체이지만 일반 객체와는 다름
- 일반 객체는 호출할 수 없지만, 함수는 호출 가능
- 일반 객체가 가지고 있는 내부 슬롯/내부 메서드와 함수로서 동작하기 위해 함수 객체만을 위한
[[Environment]], [[FormalParameters]] 등의 내부 슬롯과 [[Call]], [[Construct]] 같은 내부 메서드 추가 소유
- 함수가 일반 함수로서 호출되면 함수 객체의 내부 메서드 [[Call]]이 호출되고,
함수가 new 연산자와 함께 생성자 함수로서 호출되면 내부 메서드 [[Construct]]이 호출됨
- 내부 메서드 [[Call]]을 갖는 함수 객체 => callable, 내부 메서드 [[Construct]] 같는 함수 객체 => constructor
[[Construct]]를 갖지 않는 함수 객체 => non-constructor (객체를 생성자 함수로서 호출할 수 없는 함수)
- 함수 객체는 반드시 callable, 하지만 모든 함수 객체를 생성자 함수로서 호출할 수는 X
- 일반 함수로서만 호출 가능한 객체 (non-constructor)
일반 함수 또는 생성자 함수로서 호출할 수 있는 객체 (constructor)
- constructor와 non-constructor의 구분
- JS 엔진이 함수 정의 방식에 따라 함수를 constructor와 non-constructor로 구분
- constructor(생성자 함수로서 호출 가능한 함수): 함수 선언문, 함수 표현식, 클래스(함수)
- non-constructor(생성자 함수로서 호출 불가능한 함수): 메서드(ES6 축약), 화살표 함수
- 일반 함수로 정의된 함수만이 constructor
- new arrow(); // TypeError: arrow is not a constructor
- ECMAScript 사양에서는 ES6 메서드 축약 표현만 메서드로 인정 (그 외는 모두 일반 함수)
- 모든 함수 객체는 [[Call]] 이 구현되어 있음
- new 연산자
- new 연산자 없이 생성자 함수를 호출하면 일반 함수로 호출됨
- 함수 내부의 this는 전역 객체를 가리킴
- 생성자 함수는 첫 문자를 대문자로 기술하는 파스칼 케이스로 구분하도록 노력
- new.target
- ES6 new.target 지원 (IE에서는 지원 X)
- this와 유사하게 constructor인 모든 함수 내부에서 암묵적인 지역 변수와 같이 사용됨 (메타 프로퍼티)
- 함수 내부에서 new.target 사용 => new 연산자와 함께 생성자 함수로서 호출되었는지 확인 가능 (재귀적 구현)
- new 연산자와 함께 생성자 함수로서 호출되면 함수 내부의 new.target은 함수 자신을 가리킴,
일반 함수로서 호출된 경우면 new.target은 undefined
- 스코프 세이프 생성자 패턴 (new.target 사용할 수 없는 상황 - this instanceof 구문 사용하여 재귀적 구현)
- new 연산자와 함께 생성자 함수에 의해 생성된 객체(인스턴스)는 프로토타입에 의해 생성자 함수와 연결됨
- 대부분의 빌트인 생성자 함수는 new 연산자와 함께 호출되었는지 확인 후 적절한 값 반환
'Books > 모던 JS Deep Dive ✔️' 카테고리의 다른 글
[모던 JS Deep Dive] 19장 - 프로토타입 (0) | 2021.12.30 |
---|---|
[모던 JS Deep Dive] 18장 - 함수와 일급 객체 (0) | 2021.12.22 |
[모던 JS Deep Dive] 16장 - 프로퍼티 어트리뷰트 (0) | 2021.12.20 |
[모던 JS Deep Dive] 15장 - let, const 키워드와 블록 레벨 스코프 (0) | 2021.12.15 |
[모던 JS Deep Dive] 14장 - 전역 변수의 문제점 (0) | 2021.12.15 |
댓글