let counter1 = {
value: 0,
increase: function() {
this.value++ // 메서드 호출시 this는 counter1
},
decrease: function() {
this.value--
},
getValue: function() {
return this.value
}
}
counter1.increase()
counter1.getValue() // 1
이 경우 단 1개의 객체가 생성된다.
그래서 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 한다면 매번 같은 프로퍼티를 기술해야 하므로 비효율적이다.
이 문제를 해결하기 위해 생성자 함수가 등장한다.
//생성자 함수
function Circle(radius) {
// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
this.radius = radius;
this.getDiameter = function(){
return 2*this.radius;
};
}
//인스턴스 생성
const circle1 = new Circle(5)
const circle2 = new Circle(10)
console.log(circle1.getDiameter()); //10
console.log(circle2.getDiameter()); //20
생성자 함수로 객체를 생성한다면 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있다.
함수호출방식 | this가 가리키는 값(바인딩) |
---|---|
일반 함수로 호출 시 | 전역객체 |
메서드로 호출 시 | 메서드를 호출한 객체 |
생성자 함수 호출 시 | 생성할 인스턴스 |
function makeCounter() {
let value = 0;
return {
increase: function() {
value++;
},
decrease: function() {
value--;
},
getValue: function() {
return value;
}
}
}
let counter1 = makeCounter()
counter1.increase()
counter1.getValue() // 1
let counter2 = makeCounter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2
이 주제는 광범위하므로 "클래스" 포스트에서 소개하려고 한다.
따라서
함수 객체 = 일반객체가 가진 내부 슬롯과 메서드 + 함수객체만을 위한 내부 슬롯과 [[Call]], [[Constructor]] 와 같은 내부 메서드를 추가로 가지고 있다.
위에서 정리한 이유는 일반 함수와 생성자 함수의 차이를 설명하기 위함이다.
function foo(){}
foo(); // 일반 함수 호출 [[Call]] 호출
new foo(); // 생성자 함수 호출 : [[Constructor]] 호출
내부메서드 [[Constructor]] 를 갖는 함수 객체를 constructor, 즉 생성자 함수로 호출할 수 있는 함수
정리하자면
- constructor = 생성자 함수로 호출할 수 있는 함수
- non-constructor = 생성자 함수로 호출 할 수 없는 함수
자바스크립트 엔진은 위의 둘을 함수 정의를 평가해 함수 객체를 생성할 때 함수 정의 방식에 따라
함수를 constructor냐 non-constructor 냐 구분한다
- constructor: 함수 선언문, 함수 표현식, 클래스
- non-constructor: 메서드(ES6 메서드 축약표현), 화살표 함수
- constructor: 함수 선언문, 함수표현식, 클래스
prototype 프로퍼티가 있다.
- non-constructor: 메서드, 화살표 함수
prototype 프로퍼티가 없다.
그런데 왜? 라고 생각할 수도 있다 .
이 개념이 나중에 나오기 때문에 미리 정리한 것이다.