JavaScript/ES6

[OOP]prototype

MoZZANG 2022. 8. 25. 09:58

이거보고 prototype 이해 못하면 자바스크립트 접으셈

 

 

 

이전포스팅에서 봤던 내용은 멋진 객체지향 용어로 상속(inheritance)이라고 합니다.

기계라는 constructor가 가진 name, age 속성들을 그대로 물려받아서 오브젝트를 하나 뽑아주는게 

뭐 재산 물려주는 상속과 비슷하다고 해서 상속이라고 부릅니다. 

(그래서 상속해주는 것은 부모, 상속받는 오브젝트들은 자식이라고 많이 비유해서 불러요)

 

근데 자바스크립트엔 constructor 말고도 상속기능을 구현할 수 있는 장치가 하나 더 있습니다. 

prototype이라는 것인데 알아보도록 합시다. 

 

 

 

기계를 만들면 prototype이라는 항목이 기계 안에 몰래 생성됩니다.

 

▲ 위의 사실이 진짜인지 확인해보고 싶으면 출력해보시면 됩니다.

여러분이 만든 기계는 전부 prototype이라는 항목을 내부에 몰래 생성합니다. 

 

그럼 뭔진 모르겠는데 뭔가 출력되긴하죠?

갑자기 알게된 prototype이라는 비밀 공간은 왜 존재하고 어디에 쓰는 거냐면.. 

이것이 바로 부모의 유전자역할을 해주는 일종의 비밀 공간이라고 보시면 됩니다. 

 

 

 

Q. 여러분 우리는 왜 키가 작고 못생겨서 컴퓨터 앞에서 개발이나 하고 있는 것일까요

A. 키가 작고 못생긴건 우리 탓이 아니라 부모님 탓입니다.

부모님이 작은 키가 들어있는 유전자를 물려줬기 때문에 키가 작은 것입니다.

마찬가지로 prototype은 자식들이 물려받을 수 있는 유전자라고 생각하시면 됩니다.

기계.prototype은 기계의 유전자입니다. 

기계.prototype 에 뭔가 변수나 함수가 들어가있다면

기계로부터 생성되는 새로운 오브젝트들(자식들)은 전부 그걸 그대로 물려받아 쓸 수 있습니다.

 

 

 

 

예를 들면 이렇게 됩니다.

저번 시간 예제 코드에 prototype 어쩌구 한줄을 추가해보겠습니다. 

 

제가 기계의 prototype이라는 곳에 { gender : '남' } 이라는 key/value 한쌍을 저장했습니다.

(prototype은 저렇게 오브젝트 자료형 다루듯이 하면 됩니다)

 

기계의 prototype, 즉 유전자에 gender : '남'이라는 데이터를 추가한 것입니다.

이제 학생1, 학생2 같은 기계로부터 생성되는 모든 자식들은 gender라는 속성을 사용할 수 있습니다. 

진짠지는 출력해보시면 되죠?

 

그래서 결론은 prototype 이라는 비밀 공간을 이용하시면 똑같이 상속기능을 만들 수 있습니다. 

 

 

 

(참고)

- prototype에는 값을 여러개 부여할 수도 있고 심지어 함수도 집어넣으실 수 있습니다. object 자료처럼 다뤄주시면 됨요.

- prototype에 추가된 데이터들은 자식들이 직접 가지는게 아니라 부모만 가지고 있습니다. 

 

 

 

 

 

 

작동원리가 궁금하지 않습니까?

 

도대체 왜 prototype에 추가한 데이터는 자식들이 자유롭게 가져다 쓸 수 있는지 안궁금하세요?

이런거 궁금해해야 나중에 커서 훌륭한 사람이 됩니다. 

그러니 같이 알아봅시다. 

 

자바스크립트는 Object에서 데이터를 뽑을 때 확인하는 순서가 있습니다. 

예를 들면

 

▲ 학생1.gender라고 사용하면 '남'이 출력되죠? 그 이유는..

자바스크립트는 오브젝트에서 값을 출력할 때 이런 순서로 물어봅니다.

(1) 학생1에 직접 gender라는 값이 있는가?

(2) 그럼 부모 유전자에 gender라는 값이 있는가?

(3) 그럼 부모의 부모 유전자에 gender라는 값이 있는가?

(4) 그럼 부모의 부모의 부모의 유전자에 .. 그게 있는가?

 

 

자바스크립트는 이런 알고리즘으로 작동합니다.

그냥 쉽게말하자면 오브젝트에서 값을 뽑을 때 

1. 내가 직접 가지고 있는지 검사

2. 내가 가지고 있지 않으면 부모 유전자들을 차례로 검사하는구나

라고 잘 기억해주시면 됩니다. 

 

 

그래서 학생1이라는 오브젝트가 gender라는 값을 가지고 있지 않지만

부모의 유전자(기계.prototype) 에 있는 gender라는 걸 출력할 수 있는 이유입니다. 

 

 

 

 

 

작동원리2 : 자바스크립트 내장함수 toString()을 쓸 수 있는 이유

 

자바스크립트 array, object 들에는 붙일 수 있는 내장함수들이 많습니다.

sort, push, toString, map, forEach 등 이런 것들을 array에 붙여서 사용가능한데 혹시 그 이유가 궁금하지 않으셨습니까.

이런거 궁금해야 고오급개발자가 됩니다. 

 

결론부터 말하자면 매우 쉽습니다. 

 

 

내가 만든 array에 arr.toString() 이렇게 붙일 수 있는 이유는

내가 만든 array의 부모 유전자가 toString()을 가지고 있기 때문입니다. (혹은 부모의 부모요)

 

 

 

 

- 내가 만든 array는 부모 기계로 부터 뽑은게 아닌데 뭔소리하는 거냐고요? 

여러분 실은 array나 object 자료형 만드실 때 부모가 있긴 있습니다. 

 

▲ 위 코드 두줄은 같은 완전 똑같은 의미입니다.

위는 인간이 array 만드는 방식, 밑은 컴퓨터가 array 만드는 방식입니다. 

사람은 귀찮아서 [] 그냥 대괄호쳐서 만드는데 내부적으로는 저렇게 new 키워드를 항상 이용해서 array/object를 만들어줍니다.  

 

 

 

그럼 new Array() 이게 뭔뜻이죠?

Array라는 기계로부터 자식을 하나 새로 뽑아주세요 라는 뜻 아닌가요?

맞습니다. 

 

그래서 Array로부터 생성된 자식들은 Array의 유전자에 부여되어있는 함수, 데이터들을 자유롭게 사용하실 수 있습니다. 

Array라는 기계의 유전자가 진짜 있는지 확인은 콘솔창에 출력해보시면 됩니다. 

 

 

이렇게 하면 뭐나옵니까. 여러분이 평소에 쓰던 sort, map, push, forEach 이런 것들이 등장합니다.

그래서 Array의 자식들은 전부 이런 함수들을 쉽게 가져다 쓸 수 있었던 것입니다. 

 

Object 자료형도  똑같이 new Object() 이런 식으로 만들어주기 때문에 부모의 prototype에 있던 함수들을 자유롭게 사용가능합니다.

이것이 내장함수들의 비밀이었습니다.

 

 

 

 

Q. 그럼 prototype으로 상속시키는거랑 constructor로 상속시키는거랑 차이가 뭐죠?

A. 자식들이 값을 직접 소유하게 만들고 싶으면 constructor로 상속시키시면 되고

부모만 가지고 있고 그걸 참조해서 쓰게 만들고 싶으면 prototype으로 상속시키면 되겠쥬?

보통은 그래서 상속할 수 있는 함수 같은 것들은 prototype으로 많이 만들어놓습니다. 

 

 

 

 

 

 

 

prototype의 특징 몇가지

 

1. prototype은 constructor함수에만 몰래 생성됩니다.

 

여러분이 일반 object, array 이런거 만들어도 거기엔 prototype이 없습니다.

끝입니다. 

그럼 일반 object 같은걸 상속하고 싶으면 어떻게 하냐고요?

constructor 함수를 만들던가.. 아니면 Object.create()를 쓰거나 class를 쓰거나 셋 중 하나 하시면 됩니다. 

 

 

 

 

2. 내 부모님 유전자를 찾고 싶다면 __proto__를 출력해보시면 됩니다.

 

부모로부터 생성된 자식 object들은 __proto__라는 속성이 있습니다.

이걸 출력해보시면 부모의 prototype이 출력됩니다.

그래서 __proto__는 부모의 prototype과 같은 의미입니다. 

 

진짜 그런지 한번 출력해봅시다. 

 

학생1.__proto__

기계.prototype

각각 출력해보시면 똑같은게 나오죠? 

아무튼 그래서 "__proto__는 부모 prototype을 의미한다" 라고 알아두시면 되겠습니다.

그냥 __proto__는 내 부모 유전자가 뭔지 유전자 검사하고 싶을 때 쓸 수 있는 그런 값이라고 생각하시면 되겠습니다. 

 

 

 

 

3. __proto__를 직접 등록하면 object끼리 상속기능을 구현가능합니다.

__proto__는 부모의 prototype을 의미한다 라고 했습니다.

그럼 어떤 object에다가 __proto__를 강제로 하나 설정해버리면 어떻게 될까요?

오 이런 부모님이 생겨버립니다. 

일종의 유전자 공학인데 한번 실험해봅시다. 

 

 

 

지금 부모와 자식 object를 하나씩 만들었습니다.

그리고 셋째줄에서 자식의 __proto__에 부모를 집어넣었습니다. 

그럼 자식의 부모 유전자는 { name : 'Kim' } 이라는 오브젝트가 되는 것입니다. 

그렇게 되면 자식은 이제 자식.name 속성을 자유롭게 사용할 수 있습니다. 

 

상속기능 구현을 이렇게도 할 수 있군요. 

 

 

 

 

4. 실은 콘솔창에 prototype 정보들이 항상 출력됩니다.

 

 

이렇게 쭉 내 부모의 부모까지 탐색할 수도 있습니다.

탐색해보시면 모든 object 자료형의 조상은 Object() 라는 기계이며 (일명 Object.prototype)

모든 array 자료형의 조상도 Object()입니다. (중간에 Array()라는 부모도 있고요)

모든 함수 자료형의 조상도 Object() 입니다.

(그래서 자바스크립트는 모든게 다 Object라고 말하는 것입니다.)

 

 

 

 

 

 

출처 : 코딩애플의 매우쉽게 이해하는 JavaScript 객체지향 & ES6 신문법

'JavaScript > ES6' 카테고리의 다른 글

[ES5]ES5방식으로 쉽게 상속하기  (0) 2022.08.25
[OOP]constructor, prototype 연습문제  (0) 2022.08.25
[OOP]Constructor  (0) 2022.08.25
[ES6]Reference data type다루기 : 복사  (0) 2022.08.24
[ES6]Spread, rest parameter 연습문제  (0) 2022.08.24