Object 생성자 함수
생성자 함수란 new 연산자와 함께 호출하여 객체를 생성하는 함수를 말한다. 빌트인 생성자 함수에 해당하는 Object 생성자 함수를 new 연산자와 함께 호출하면 빈 객체를 생성하여 반환한다.
생성자 함수
생성자 함수에 의한 객체 생성
생성자 함수는 객체를 생성하는 함수다. 생성된 객체는 인스턴스라 한다. 클래스 기반 언어와 달리 프로토타입 기반 객체지향 언어인 자바스크립트에는 생성자 함수의 형식이 따로 정해져 있지 않다. 일반 함수와 동일한 방법으로 생성자 함수를 정의하고 new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작한다. 만약 new 연산자 없이 생성자 함수를 호출하면 일반 함수로 동작한다. 생성자 함수를 이용하면 생성할 객체의 프로퍼티나 메서드를 정의하여 구조가 동일한 여러 개의 객체를 간편하게 생성할 수 있다.
생성자 함수의 인스턴스 생성 과정
함수가 생성자 함수로서 동작하려면 함수가 호출된 후 인스턴스를 생성하고 생성된 인스턴스를 초기화(인스턴스 프로퍼티 추가 및 초기값 할당) 해야 한다. 함수가 생성자 함수로 호출되면 인스턴스 생성을 위해 다음과 같은 과정을 거친 후 인스턴스를 반환한다.
인스턴스 생생과 this 바인딩
생성자 함수가 호출되면 함수 몸체의 코드가 실행되기 전에 자바스크립트 엔진에 의해 빈 객체가 생성된다. 이 객체가 인스턴스이다. 이때 인스턴스는 this에 바인딩된다. 따라서 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
인스턴스 초기화
생성자 함수 몸체에 기술된 코드가 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다. 즉 프로퍼티와 메서드를 추가하고 생성자 함수가 인수로 전달받은 초기값을 인스턴스 프로퍼티에 할당하여 초기화한다.
인스턴스 반환
생성자 함수 내부의 처리가 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다. 따라서 생성자 함수에는 반환문을 생략해야 한다. 만약 명시적으로 반환문을 작성하면, 반환값이 원시 값일 경우 무시되고 this가 반환되며 반환 값이 객체인 경우 명시된 객체가 반환된다.
내부 메서드 [[Call]]과 [[Contruct]]
생성자 함수로서 호출한다는 것은 new 연산자와 함께 호출하는 것을 말한다. 함수는 객체이므로 일반 객체와 동일하게 동작할 수 있다. 함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드를 모두 가지고있다. 다만 함수는 일반 객체와는 다른 특징을 갖고 있다. 일반 객체는 호출할 수 없지만 함수는 호출할 수 있다. 따라서 함수로서 동작하기 위한 내부 슬롯 [[Environment]], [[FormalParameter]] 과, [[Call]], [[Construct]] 같은 내부 메서드를 추가로 갖고 있다.
함수가 일반 함수로서 호출되면 함수 객체의 내부 메서드 [[Call]]이 호출되고 new 연산자와 함께 생성자 함수로서 호출되면 [[Construct]]가 호출된다. 내부 메서드 [[Call]]을 갖는 함수 객체를 callable이라 하며, 내부 메서드 [[Construct]]를 갖는 함수 객체를 constructor, 갖지 않는 함수 객체를 non-constructor라고 부른다. callable은 호출할 수 있는 객체 즉 함수를 말하며, constructor는 생성자 함수로서 호출할 수 있는 함수, non-constructor는 생성자 함수로서 호출할 수 없는 함수를 말한다. 앞서 함수에는 형식이 정해져 있지 않다고해서 혼란스러울수 있겠다. 관련된 내용을 살펴보자.
constructor와 non-constructor의 구분
ES5까지는 함수의 형식에 구분이 존재하지 않았다. ES6에 다른 함수 형식을 가지는 함수를 정의할 수 있는 방법이 고안되었다. 즉, constructor와 non-constructor는 함수 정의에 따라 구분된다.
- constructor: 함수 선언문, 함수 표현식, 클래스
- non-constructor: 메서드 축약 표현으로 정의된 함수, 화살표 함수
non-constructor인 함수는 내부 메서드 [[Construct]]를 갖지 않으므로 생성자 함수로서 호출하면 에러가 발생한다. 주의할 점은 생성자 함수로서 사용하지 않을 용도의 일반 함수가 생성자 함수로 동작할 수 있기 때문에 주의가 필요하다.
new.target
생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해서 ES6에서 도입되었다. 함수 내부에서 new.target을 사용하면 new 연산자와 함께 생성자 함수로서 호출되었는지 확인할 수 있다. new 연산자와 함께 생성자 함수로서 호출되면 함수 내부의 new.target은 함수 자신을 가리킨다. new 연산자 없이 일반함수로서 호출된 함수 내부의 new.target은 undefined다. 이를 이용하여 생성자 함수로서 호출했는지를 확인하고, 그렇지 않은 경우 new 연산자와 함께 재귀 호출을 통해 생성자 함수로서 호출할 수 있다.
'개발 > 자바스크립트' 카테고리의 다른 글
19. 프로토타입 (0) | 2022.07.14 |
---|---|
18. 함수와 일급 객체 (0) | 2022.07.12 |
16. 프로퍼티 어트리뷰트 (0) | 2022.07.10 |
15. let, const 키워드와 블록 레벨 스코프 (0) | 2022.07.10 |
14. 전역변수의 문제점 (0) | 2022.07.10 |
댓글