function Person(saying) {
this.saying = saying;
}
Person.prototype.talk = function() {
console.log(this.saying);
}
var me = new Person("안녕하세요 저는 윤병인입니다");
me.talk(); // "안녕하세요 저는 윤병인입니다"
new Person("안녕하세요 저는 윤병인입니다");
에서 무슨 일이 일어난걸까?
customNew
new의 작동방식을 이해하기 위해서 new 연산자와 비슷한 일을 하는 customNew를 구현해보자.
function customNew(constructor) {
var obj = {}; // 1. 빈 오브젝트를 만든다
Object.setPrototypeOf(obj, constructor.prototype); // 2. obj.__proto__에 constructor.prototype을 대입한다.
var argsArray = Array.from(arguments); // 3. 배열같은 오브젝트인 arguments를 배열로 만들어준다.
constructor.apply(obj, argsArray.slice(1)) // 4. 0번째 index를 제외한 나머지 값들을 인자값으로 넣어준다.
return obj; // 5. obj를 return한다.
}
1. 빈 오브젝트 생성
new 키워드를 함수에 쓰면, 먼저 빈 오브젝트(obj
)가 하나 만들어 진다.
2. prototype 넘겨주기
obj
의 __proto__
속성에다가 생성자 함수(Person
)의 prototype
을 넘겨준다. 이렇게 하면, obj
에서도 talk()
함수를 쓸 수 있게된다.
3. constructor함수에 this를 obj로하고 인자값 넘겨주면서 함수 실행
Person
함수의 this
를 obj
로 설정하고, customNew
에 들어온 인자값중 constructor
를 제외한 나머지를 Person
함수에 넘겨준다. 여기서는"안녕하세요 저는 윤병인입니다."
가 saying
이 되서 Person
함수에 넘어간다. 참고로 arguments
는 어떤 함수에 넘어온 인자값들을 배열 비스무리한 오브젝트 형태로 갖고있기 때문에, 이걸 배열로 바꿔주고 slice(1)
로 0번째 인덱스에 있을 constructor
를 제거한것이다.
apply
했으니까, Person
함수의 this
가 obj
가 된 상태로 Person
함수가 실행된다. 그러면 당연히 obj.saying
이 "안녕하세요 저는 윤병인입니다."
로 설정될것이다.
4. return obj
마지막으로 obj
를 리턴하면서 customNew
함수가 끝이난다.
실제 new
연산자도 customNew
처럼 작동할것이다.
테스트
function Person(saying) {
this.saying = saying;
}
Person.prototype.talk = function() {
console.log(this.saying);
}
function customNew(constructor) {
var obj = {}; // 1. 빈 오브젝트를 만든다
Object.setPrototypeOf(obj, constructor.prototype); // 2. obj.__proto__에 constructor.prototype을 대입한다.
var argsArray = Array.from(arguments); // 3. 배열같은 오브젝트인 arguments를 배열로 만들어준다.
constructor.apply(obj, argsArray.slice(1)) // 4. 0번째 index를 제외한 나머지 값들을 인자값으로 넣어준다.
return obj; // 5. obj를 return한다.
}
var me = customNew(Person, "안녕하세요 저는 윤병인입니다.");
me.talk(); // "안녕하세요 저는 윤병인 입니다."
me.talk()
는 "안녕하세요 저는 윤병인입니다."
를 출력한다!