prototype의 이해하기 힘든 현상

지금 prototype공부하고 있는데 기본적인 개념 자체는 그렇게 어렵지 않지만

깊이 들어가려니 상당히 복잡한 것 같습니다.

특히 이상한 현상을 발견했는데,

객체가 다른 prototype으로부터 상속을 받았을 경우

상속 받기 전 constructor에 접근 하는 것이 불가능한 깨짐 현상이 나타납니다.

아래 코드가 그 예인데

function Foo(){} //Foo constructor 생성

function Bar(){} //Bar constructor 생성

Bar.prototype = Foo.prototype; //직접 상속받기

var bar_instance = new Bar();

console.log(bar_instance.constructor); //bar 인줄 알았는데, foo가 나옵니다.

console.log(bar_instance instanceOf Bar); //true 입니다.

이제 Bar 생성자를 직접 사용하는 방법 외에 Bar에 접근하는 방법은

더이상 존재하지 않는 것으로 보입니다.

bar_instance의 참조 프로토타입도, 생성자도 Foo.prototype과 Foo가 되어

마치 Bar는 사라진 것으로 보입니다.

proto 개baby

현재 위의 그림이 제가 작성한 코드의 구조입니다. 위에서 중요한 점은 위에서 말했듯이

Bar 생성자에 접근을 할 수 없다는 점입니다.

Bar로 생성된 객체들은 constructor와 __proto__를 사용할 경우에도, 또 Bar.prototype을 이용하더라도

Foo로만 접근하게 됩니다.

이렇게 사라진 것으로 보이는 Bar가, instanceof 연산자를 통할경우 bar_instance가 Bar의 인자라는 것을 어떻게 확인한 것인지 궁금하네요!

이 구조에서 Bar 에 접근할 수 있는(Bar를 직접 수정하는 것 이외에) 방법이 있는지도 궁금합니다.

.

그리고 이 부분은 상속은 아니고 레퍼런스를 대치해버린거죠…

1개의 좋아요

윗분처럼 해야 하는 이유는, 질문처럼

Bar.prototype = Foo.prototype;

이렇게 했을 시, 레퍼런스 대입이 되기 때문에,
Bar.prototype에 변경이 일어날 경우 Foo.prototype 에도 영향이 미치게 됩니다.
그렇게 되면 부모 클래스라는 의미가 퇴색되는거죠.
그렇기 때문에 기존 프로토타입에서 입 싹 닫고 새로이 대입하여 수박이라 치면, 수박 식물 째로 영향받지 않고, 수박 열매만 적용하도록 생각하시면 됩니다.
그리고 마지막으로 레퍼런스 특성 상 결국 Foo 소속이기 때문에

Bar.prototype.constructor = Bar;

이런 식으로 생성자를 덮어버려서 완벽한 Bar의 Foo 상속 효과를 얻게 되는거죠.

네. 상속은 맞긴 맞아요. 단지 상속 효과를 내기 위한 방법론일 뿐이죠.

2개의 좋아요

prototype객체와 constructor객체는 서로 참조하고 있습니다. Bar의 prototype을 Foo의 prototype으로 overwrite했기때문에
Bar.prototype.constructor와 Foo.prototype.constructor가 모두 Foo입니다. 따라서

bar_instance.constructor

는 Foo가 나옵니다.
그리고 instanceof 라는 키워드는 bar_instance라는 객체의 프로토타입 체인 내에 constructor로 Bar의 constructor가 있는지를 확인할텐데, Bar.prototype.constructor가 Foo이기 때문에 true입니다.

추가 : A instanceof B 는 A의 프로토타입체인 내에 B.prototype이 있는지를 확인하는 식으로 동작하기때문에

Bar.prototype == Foo.prototype ==  bar_instance.__proto__

여서 true입니다. 만약

bar_instance.__proto__ = Foo.prototype

처럼 했다면

bar_instance instanceof Bar

는 false일겁니다.

3개의 좋아요

그 부분에 대해서도 글을 쓸 예정입니다. 저문제가지고 고민하다보니

프로토타입이 좀 이해가 가는 것 같습니다

그런 방법이 있었군요! 답변 감사합니다.

@ho1234c
가장 확실한 답변이라고 생각해요!! 답변 감사합니다

그런데 예제를 실행해 보니 false가 아니라 true로 나오네요

@pDestiny scope내에서 뭔가 다른 코드를 실행하셨을것같아요. 제 예시는 아래와 같은 상황입니다 :slight_smile:

function Bar(){};
function Foo(){};
var bar_instance = new Bar();
bar_instance.__proto__ = Foo.prototype
bar_instance instanceof Bar // false 입니다.
1개의 좋아요

@ho1234c 아하! 이제 알았습니다!!!
Bar.prototpye과 Bar로 만들어낸 인스턴스가 가르키는 프로토타입이 다를 수 있는거군요!!

instanceof가 어떻게 작동하는지 이해 할 수 있을 것 같습니다.

예제는 확실히 false네요 ㅎ

답변 감사합니다.