생성자 함수란?
자바스크립트가 기본 제공하는 빌트인 함수로 동일한 형태의 객체를 만들때 사용하는 함수이다.
new 연산자와 함께 호출하면 함수 객체를 생성해서 반환한다. new키워드를 사용하지 않으면 일반적인 함수와 동일하게 동작하여 새로운 객체를 반환하지 않는다.
const twosum1 = {
num : 5,
goSum() {
return 2 + this.num;
}
};
const twosum2 = {
num : 10,
goSum() {
return 2 + this.num;
}
};
2를 더한 값을 리턴하는 함수가 있다고 가정하자.
동일한 프로퍼티를 갖는 객체를 여러개 생성해야 하는 경우 이렇게 객체 리터럴에 의한 생성방식은 비효율적이다. 객체마다 프로퍼티 값은 다르지만 프로퍼티나 메서드는 동일하기 때문이다.
function Twosum(n) {
this.num = n;
this.gosum = function() {
return 2 + this.num;
}
};
생성자 함수에 의한 객체 생성방식은 프로퍼티 구조가 동일한 객체를 여러 개 만들때 간편하게 생성할 수 있다. 이때 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스(객체)를 가리킨다.
const twosum1 = twosum(5); // 일반 함수 호출
const twosum2 = new Twosum(10); // 생성자 함수 호출
이렇게 생성자 함수로 객체를 만들때는 new 연산자와 함께 함수를 호출한다. new 연산자를 사용하지 않고 함수를 호출해도 함수는 호출이 되지만 '생성자 함수'로는 호출되지 않는다. 따라서 일반 함수로 호출된 twosum은 반환문(return문)이 없어서 undefined를 반환한다.
생성자 함수의 역할은 '인스턴스를 생성하는 것'과 '생성된 인스턴스를 초기화하는 것'이다.
위 예시에서 생성자 함수 살펴보면 this에 프로퍼티(num)를 추가하고 전달된 인수(n)를 프로퍼티의 초기값으로 할당하여 인스턴스를 초기화한다. 이 과정에서 인스턴스를 생성하는 것은 필수지만, 생성된 인스턴스를 초기화하는 것은 옵션이다.
하지만 우린 인스턴스를 생성하고 반환하는 코드를 따로 넣지 않는다. 그 이유는 자바스크립트 엔진은 암묵적인 처리를 통해 인스턴스를 생성하고 반환하기 때문이다. new 연산자와 함께 생성자 함수를 호출하면 자바스크립트 엔진은 암묵적으로 인스턴스를 생성하고 인스턴스를 초기화한 후 반환한다.
생성자 함수가 호출되면 빈 객체가 생성되며 이 객체는 this에 바인딩된다.
(여기서 바인딩이란? 식별자(변수이름)과 값을 연결하는 과정을 의미.)
이것이 바로 this가 객체를 가리키는 이유이다.
this에 바인딩되어 있는 인스턴스(객체)에 프로퍼티나 메서드를 추가하고 생성자 함수가 인수로 전달받은 초기값을 프로퍼티에 할당하여 초기화하거나 고정값을 할당한다.
마지막으로 완성된 인스턴스가 바인딩된 this를 반환한다. 여기서 만일 생성자 함수에 return값으로 객체{}를 반환하면 this가 무시되고 객체를 반환하며 원시값(변경 불가능한 값)을 반환하면 원시값은 무시되고 this가 반환된다.
function Twosum(n) {
this.num = n;
this.gosum = function() {
return 2 + this.num;
}
return 200; //원시값
};
그러므로 생성자 함수에서 return 문을 반드시 생략해야 한다.
일반 함수와 생성자 함수는 특별한 차이가 없다. 단지 new 연산자와 함께 함수를 호출할때만 생성자 함수로 동작할 뿐이다. 그래서 우리는 암묵적인 약속으로 생성자 함수의 첫글자를 대문자로 적어 개발자들끼리 알아볼 수 있게 표시한다.
new 연산자와 함께 함수를 호출하면 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다. 하지만 일반 함수를 호출하면 함수 내부의 this는 전역객체인 window를 가리킨다.
위의 예시에서 보면 num은 생성자 함수가 생성한 인스턴스의 프로퍼티가 되고 n으로 들어오는 매개변수는 프로퍼티 값이 된다. 그리고 gosum 메서드는 생성자 함수가 생성할 인스턴스의 메서드가 된다.
생성자 함수에대해 제대로 공부하기 전까지는 생성자 함수가 정확히 무엇인지, 왜 new를 쓰고 this를 사용해야 하는지 잘 몰랐는데 이번에 정리하면서 공부하니 제대로 이해를 한 것 같다. 내일은 this 키워드에대해 정리해볼 생각이다. 알면 알수록 자바스크립트는 점점 어려워지지만 그만큼 재미도 있다.