생성자 함수를 호출할 때 this 바인딩
생성자 함수가 동작하는 방식
new
연산자로 자바스크립트 함수를 생성자로 호출하면, 다음과 같은 순서로 동작한다.
1.빈 객체 생성 및 this 바인딩
생성자 함수가 실행되기 전 빈객체가 생성된다. 바로 이 객체가 생성자 함수가 새로 생성하는 객체이며, 이 객체는 this
로 바인딩 된다. 따라서 이후 생성자 함수의 코드 내부에서 사용된 this
는 이 빈 객체를 가리킨다.
생성자 함수가 생성한 객체는 자신을 생성한 생성자 함수의 prototype
프러퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다.
2.this를 통한 프로퍼티 생성
함수 내부에서 this
를 사용해서, 앞에서 생성된 빈 객체에 동적으로 프로퍼티나 메서드를 생성할 수 있다.
3.생성된 객체 리턴
리턴문이 없을 경우, this
로 바인딩된 새로 생성한 객체가 리턴된다. 이것은 명시적으로 this
를 리턴해도 결과는 같다. 하지만 다른 객체를 반환하는 경우는 생성자 함수를 호출했다고 하더라도 this
가 아닌 해당 객체가 리턴된다.
객체 리터럴 방식과 생성자 함수를 통한 객체 생성 방식의 차이
객체 리터럴 방식으로 생성된 객체는 같은 형태의 객체를 재생성할 수 없는 반면 생성자 함수를 사용해서 객체를 생성한다면, 생성자 함수를 호출할 때 다른 인자를 넘김으로써 같은 형태의 서로 다른 객체를 생성할 수 있다.
var foo = {
name: 'foo',
age: 35,
gender: 'man'
};
console.dir(foo);
function Person(name, age, gender, position){
this.name = name;
this.age = age;
this.gender = gender;
}
var bar = new Person('bar', 33, 'woman');
console.dir(bar);
var baz = new Person('baz', 25, 'woman');
console.dir(baz);
객체 리터럴 방식과 생성자 함수 방식의 차이는 프로토타입 객체(proto 프로퍼티)에 있다. 객체 리터럴 방식의 경우는 자신의 프로토타입 객체가 Object인 반면 생성자 함수의 경우는 Person 으로 서로 다르다.
이렇게 차이가 발생하는 이유는 자바스크립트 객체 생성 규칙 때문이다. 자바스크립트 객체는 자신을 생성한 생성자 함수의 prototype
프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다.
객체 리터럴 방식에서는 객체 생성자 함수는 Object() 이며, 생성자 함수 방식의 경우는 생성자 함수 자체이다.
생성자 함수를 new를 붙이지 않고 호출할 경우
일반 함수 호출의 경우는 this
가 window
전역 객체에 바인딩되는 반면에, 생성자 함수 호출의 경우 this
는 새로 생성되는 빈 객체에 바인딩된다.
다음은 강제로 인스턴스를 생성하는 방법으로 일반 함수로 호출되는 위험성을 피하려고 널리 사용되는 패턴이다.
function A(arg){
if(!(this instanceof arguments.callee))
return new A(arg);
this.value = arg ? arg : 0;
}
여기서 arguments.callee
는 호출된 함수를 가리킨다.