2008. 7. 18. 16:15
prototype의 constructor에 대한 질문.

function A(){
  this.a = 'a';
}

function B(){
  this.b = 'b';
}


위와 같은 함수가 있을때,

★예제 1.

A.prototype = B.prototype;

var obj = new A;

-- 예제1의 결과

obj.constructor // function B(){ this.a = 'b'; }
A.prototype.constructor //function B(){ this.a = 'b'; }
obj.a // a
obj.b //undefined

★예제 2.

A.prototype = new B

var obj = new A;

-- 예제2의 결과

obj.constructor // function B(){ this.a = 'b'; }
A.prototype.constructor //function B(){ this.a = 'b'; }
obj.a // a
obj.b // b

-- 궁금증 --

예제1 에서 보시면 obj의 생성자도 B고 A.prototype의 생성자또한 B입니다.
그런데, obj는 B를 참조하지 못하고 있습니다.
(예제에는 없지만 B.prototype은 참조하고 있습니다.)

저는 A.prototype 에 B.prototype을 할당하면 B도 같이 넘어오는것 처럼 보이는데,

실제로 결과를 확인해보니 B의 prototype개체만 넘어옵니다.

그렇다면 왜,, A.prototype.constructor와 obj.constructor는 B가되는것일까요??
A가 참조하지 않는다면, 생성자는 그대로 A가되야 하지 않을까요?

그리고 예제2에서 처럼 new연산자를 통해서 A.prototpye = new B를 하면 prototpye과

생성자가 같이 넘어오는 건가요..?

정리를 한다고 했는데,, 제가 질문하는 의도가 그대로 전달되는지 조심스럽네요^^;

답변 부탁드립니다.


---------------------------------------------------------


아즈키의 답:

A.prototype 나 B.prototype 이 생성된 과정을 생각하세요..
그리고 A.prototype 이나 B.prototype 은 A와 B와는 별개라고 생각하세요..
B.prototype 은
function B(){
this.b = 'b';
}
을 쓰신 순간에 생성되고,
그리고, B.prototype 의 생성자 (constructor) 는 B 가 되겠죠..
(B.prototype.constructor == B)

A.prototype = B.prototype;
를 하셔서 이제.
A.prototype 는 B.prototype 가 되고.(똑같은객체)
A.prototype.constructor 는 B가 됩니다.
(B.prototype.constructor 는 B 이니까요.) 삭제
아즈키     그 리고, new A 로 해서 만든 obj 의 경우의 implicit prototype link는 B.prototype 을 가르키고 있겠죠.. (참고: FF에서는 __proto__ 라는 키워드로 implicit prototype link를 확인할 수 있습니다)
그래서 a.constructor == B 가 되는겁니다. (실제적으로 a 는 constructor 라는 프로퍼티를 가지지 않습니다. constructor 는 a 의 implicit prototype link 인 B.prototype 에서 받아오는 것 입니다.)

A.prototype = new B
하신것은 new B 해서 나온 object를 A.prototype 으로 쓰겠다는 것 인데요..
그럼 obj = new A 해서 생긴 obj 의 constructor 는
obj 의 implicit prototype link 인 "new B 해서 나온 object"의 implicit prototype link인 B.prototype 의 constructor 인 B 가 나오고요.
A 의 prototype 은 "new B 해서 나온 object" 이므로, 마찬가지이고요. 삭제
아즈키     그리고,
obj.a 는 new A 할 때 생긴 프로퍼티고, obj.b 는 new B 할 때 생긴 거니 둘다 됩니다..
물론, obj.a 는 obj 자체가 가진 프로퍼티지만, obj.b 는 obj 의 implicit prototype link 인 "new B 해서 나온 object"가 가진 프로퍼티죠..

아마도, prototype 의 개념에 대해서 조금 오해를 하고 계신 것 같습니다.
ecma4-262 문서를 보시면 도움이 되실 것 같습니다. (특히 4.2.1 Object 파트를 보시면.) 삭제
hym73     친절하고 상세한 답변 정말 많은 도움되었습니다.
감사드립니다.

덧붙여 질문하나 드리자면,, 답변에서 말씀하고 계신 "implicit prototype link"가 무엇을 뜻하는지요?^^
아즈키     네. implicit prototype link 라는건 자세한건 문서를 보시면 (ecma) 좋습니다.
특히 자바스크립트에서는 이게 이거다 하는 말이 많은데.. (OOP다, 아니다. function 이다, object 다. class 다 아니다 등등)
일단은 ecma 스펙문서에 나온 단어구요.
대략적으로 설명드리면..
explicit prototype link 와 implicit prototype link 가 있습니다.
var A = function() {};
var Ap = A.prototype;
var a = new A();
위와 같은 예제에서,
A의 explicit prototype link가 Ap이고
a의 implicit prototype link가 Ap입니다.
explicit 단어를 붙인 것은 A.prototype 으로 명시적으로 접근할 수 있기 때문인 것 같습니다.
implicit 단어를 붙인 것은 a 에서 Ap에 명시적으로 접근을 할 수 없기 때문인 것 같네요.. (하지만 FF에서는 __proto__ 라는 키워드를 만들어서 접근할 수 있도록 했습니다) 삭제
아즈키     그럼 역활에 관해 좀 더 설명드리자면.

위 예제에서
Ap.b = 23;
하면
a.b == 23
이 true 입니다.
실제적으로 a 가 b 를 가지고 있는 것이 아니고, Ap 에서 가져오는 것이죠..
이것이 implicit prototype link 입니다.

그리고 부가적인 설명을 드리자면
a의 implicit prototype link인 Ap의 implicit prototype link가 만약 Cp라면..
Cp.c = 84;
했을 때, a.c == 84 가 true 입니다
즉, 자기 자신이 그 멤버(프로퍼티)를 안 가지고 있으면 implicit prototype link를 따라 계속 탐색을 합니다.
이것을 prototype chain 이라고 부릅니다.

조금이나 도움이 되었다니 제가 더 감사합니다 좋은 하루 되세용
Posted by 아즈키