본문 바로가기
Javascript, ES5, ES6

Javascript Prototype 에 관하여 정리해 봅니다 # JS 상속

by Developer88 2021. 4. 27.
반응형

자바스크립트는 prototype을 베이스로 한 언어라고 하는데요.
ES2015에서부터 class라는 단어가 나오기 시작하였지만,
여전히 Javascript는 prototype 베이스의 언어입니다.
오늘은 이러한 JS의 prototype에 대해서 알아보겠습니다.

 

1. prototype 과 prototype Chain

1-1. prototype 과 prototype Chain

prototype을 이해하기 위해서 아래의 객체를 보도록 하겠습니다.

students라는 객체에는 fullName이라는 속성만 지정되어 있는데요.

'students.' 이라고 입력하면, 본적없는 속성들이 IDE에 아래와 같이 나열되는 것을 볼 수 있습니다.

 

 

이렇게 객체만 만들어도 접근할 수 있는 property에는 다음과 같은 값들이 있습니다.

 

 

이 값들은 어떻게 나온 것 일까요?

 

JS의 모든 객체들은,

prototype이라는 private한 property를 가지게 되는데요.

이 prototype이라는 것이 부모객체가 가지는 속성에 대한 링크를 가지므로,

부모의 속성들을 그대로 사용할 수 있게 해 줍니다.

당연히 부모의 부모의 부모의 prototype까지도 사용가능합니다.

 

위에서 본 여러가지 속성들(hasOwnProperty, toString 등등)은 객체들의 최고부모인 Object의 속성들입니다.

prototype을 거슬러 올라가 Object.prototype의 속성들에 접근할 수 있기에 저런값들이 나오는 것 이지요.

이렇게 거슬러 올라가는 것을 prototype Chain 이라고 합니다.

 

 

해당 객체에 대해 사용가능한 property들을 찾을 때,

다음의 property들을 모두 다 찾아냅니다.

  • 객체 자신의 property
  • prototype의 property
  • 그리고 prototype의 prototype의 property

 

 

마치 러시아 인형 마트로시카처럼,

각 객체들은 prototype 은 prototype 객체의 링크를 따라 올라가 부모들의 속성을 전부 사용할 수 있는 것 이지요.
이런식으로 prototype링크를 따라가다가다 보면, null이 될 때가지 계속 올라갈 수 있는데요.
null은 prototype을 가지고 있지 않고 있어서, prototype의 final link가 되기도 합니다.

 

 

이해하기 쉽게 단순화하자면,

prototype속성은 부모속성으로의 연결고리라고 할 수 있을 것 같네요.

부모는 그 부모의 속성에 대한 연결고리를 가지고 있구요.

JS는 상속을 할 때 이 prototype이라는 속성을 이용합니다.

 

1-2. When

그럼 언제 이 prototype을 사용해야 할 까요?

코드를 보면서 이해해 보겠습니다.

 

 

 

"tesla"객체의 부모인 Car.prototype 에 honk라는 함수를 추가시켜주었는데요.

이는 다른 Car 객체인 "ev8"에도 사용할 수 있게 되었습니다.

 

JS에서는 이렇게 부모로부터 속성을 상속받아서, 상속받은 모든 객체들에게서 사용할 수 있도록 할 때,

prototype이라는 속성을 수정해서 이용할 수 있습니다.

다른언어와는 사뭇 다른 모습이네요.

 

prototype을 이용한 다양한 상속과 실제 코드를 보면서 이해해 보겠습니다.

 

2. prototype 과 상속

2-1. 상속 part1

가장 먼저 볼 상속방법은 위에서도 잠시 보았던 것인데요.

한번 더 보도록 하겠습니다.

 

ProtoTester()라는 함수에 prototype을 이용해서 상속이라는 것을 구현해 보겠습니다.

원래 객체의 점수에 10점을 더해서 return해주는 함수를,

prototype에 넣어줍니다.

아래 결과로 console에 찍히는 값은 90점입니다.

 

 

 

t2 객체에서도 higerScore()를 실행시켜서, 10점이 올라간 90점과 70점의 결과값을 얻을 수 있습니다.

higherScore만 다르게 정의한다면, t1, t2 두객체의 값도 달라지게 될 것이구요.

ProtoTester에 직접 정의하지 않았으므로, 객체 생성시마다 불필요하게 매번 실행되거나 저장되지도 않습니다.

 

 

다른 언어의 상속에서 그랫던 것처럼,

아래와 같이 해당 객체에 대해서만 다르게 정의해서 사용할 수도 있습니다.

이제 김군과 박군은 모두 90점이 나오게 됩니다.

왜냐하면, t2는 이미 higerScore속성을 가지고 있어서,

굳이 prototype chian을 거슬러 올라갈 필요가 없기 때문입니다.

 

 

 

다시 한번 정리해 보면, JS에서는 객체에서 해당 Property를 가지고 있는지를 먼저 보구요.

없다면, prototype link를 타고 올라가서, prototype에 해당 속성이 있는지 보게 됩니다.

t2의 경우, 객체에 새롭게 higherScore라는 Property를 정의했으므로, prototype으로 찾아올라가지 않고,

자신에게 정의된 것을 사용하여서 +30점을 하여, 90점이 된 것이지요.

 

보통 함수의 경우, prototype에 정의해서 사용하는 경우가 많습니다.

 

2-2. 상속 part2

이번에도 상속에 대해서 볼 텐데요.

먼저 코드를 보겠습니다.

'ProtoTestChild.prototype'에 "new ProtoTest()"를 넣어서 부모가 될 객체를 넣어줌으로서,

ProtoTest와 ProtoTestChild간의 상속관계가 형성될 수 있습니다.

이렇게 하면,

ProtoTestChild의 객체인 mChild가 ProtoTest객체의 higherScore의 Property에 접근할 수 있습니다.

 

 

 

이번에는 상속의 상속을 보도록 하겠습니다.

Fun은 ParentFun을 상속받고, ParentFun은 GrandParentFun을 상속받습니다.

그래서, Fun이 정의한 적 없는 score Property에 접근할 수 있는 것 이지요.

 

 

결과값에 88이 정상적으로 찍히는 것을 볼 수 있습니다.

 

 

위에서 객체들의 정점에 있는 Object의 prototype까지 link가 되어있으므로,

Object에 도달할때까지 prototype link를 따라가게 되어있다고 하였는데요.

그렇기 때문에 아래의 t1에서 정의한 적이 없는,

hasOwnProperty와 같은 Property들에도 접근할 수 있는 것 입니다.

 

 

3. prototype 실제 사례들

실제 코드에서의 사례들도 보도록 하겠습니다.

아래는 구글에서 공개한 샘플코드 인데요.

FriendlyEats함수를 정의하고, getCleanPath같은 함수들은 prototype에 정의해서 사용한 것을 볼 수 있는데요.

이제 FriendlyEats의 객체, 그리고 그 자식들은 모두 getCleanPath()함수를 이용할 수 있게 되었습니다.

 

 

이상으로 prototype에 대해서 정리해 보았습니다.

업데이트 할 내용이 있거나, 좀 더 좋은 방식이 있다면 이 글을 통해 업데이트 하도록 하겠습니다.

 

728x90

댓글