[자바스크립트] 프로토타입 (Javascript - prototype)

남양주개발자

·

2016. 10. 10. 16:16

728x90
반응형



자바스크립트 프로토타입이란?



자바스크립트를 처음 접할 때 제일 이해하기 어려웠던 개념 중 하나가 바로 프로토타입이었습니다. 하지만 자바스크립트를 학습하는데 있어서 꼭! 정복해야할 산이기도 한 프로토타입을 오늘 정리해보도록 하겠습니다.

이번 기회를 통해 제대로 프로토타입을 이해하고 넘어가길 바랍니다.

(사실 저도 머릿속에 제대로 넣기 위해 포스팅합니다...)

 

자바스크립트는 클래스라는 개념이 없습니다.

그래서 기존의 객체를 복사하여 새로운 객체를 생성하는 프로토타입 기반의 언어입니다. 프로토타입 기반 언어는 객체 원형인 프로토타입을 이용해서 새로운 객체를 만들어냅니다.

이렇게 생선된 객체 역시 또 다른 객체의 원형이 될 수 있습니다.


프로토타입은 객체를 확장하고 객체 지향적인 프로그래밍을 할 수 있게 도와주는 녀석입니다. 프로토타입은 2 가지로 해석이 되는데요. 하나는 프로토타입 객체를 참조하는 prototype 프로퍼티와 객체 속성인 _proto_ 속성이 참조하는 숨은 링크가 있습니다.


이 둘의 차이점을 이해하려면 자바스크립트의 함수와 객체의 내부적인 구조를 이해 해야합니다.


함수와 객체의 내부 구조


자바스크립트에서는 함수를 정의하고, 실행을 해보면 내부적으로 수행되는 작업이 있습니다. 함수의 속성으로 prototype 프로퍼티가 있습니다. 이 속성은 다른 곳에 생성된 함수이름의 프로토타입 객체를 참조합니다. 프로토타입 객체의 속성인 constructor 속성은 함수를 참조하는 내부구조를 가집니다.

아래와 같이 표현됩니다



속성이 하나도 없는 Person이라는 함수가 정의되고, 파싱단계에 들어가면, Person 함수 prototype 프로퍼티는 Person 프로토타입 객체를 참조합니다. 프로토타입 객체 속성인 constructor 속성은 Person 함수를 참조하는 구조를 가집니다.

여기서 알아야 하는 부분은 Person 함수의 prototype 프로퍼티가 참조하는 프로토타입 객체는 new라는 연산자와 Person 함수를 통해 생성된 모든 객체의 원형이 되는 객체입니다. 생성된 모든 객체가 참조한다는 것을 기억해야 합니다. 




new라는 연산자와 Person 함수를 통해 생성된 park 객체는 __proto__가 객체를 참조하고 있다는걸 표시해주고 있네요.

그 객체는 어떤 객체일까요?

바로 constructor가 Person 함수를 가리키고 있는 Person 프로토타입 객체랍니다.

머릿속으로 천천히 복기해보세요!  잘 생각해보시면 위 표가 머릿속에 그려지실겁니다.


프로토타입 객체란?


함수를 정의하면 다른 곳에 생성되는 프로토타입 객체는 자신이 다른 객체의 원형이 되는 객체입니다. 모든 객체는 프로토타입 객체에 접근할 수 있습니다.프로토타입 객체도 추가적으로 프로퍼티와 메서드를 추가할 수 있고, 같은 원형을 복사로 생성된 모든 객체는 추가된 이러한 프로퍼티와 메서드들을 사용할 수 있습니다.



함수 안의 prototype 프로퍼티를 사용하여 프로토타입 객체에 메서드를 하나 추가했습니다. 프로토타입 객체에 getType() 이라는 메서드를 추가하면 메서드를 추가하기 전에 생성된 객체에서도 추가된 메서드를 사용할 수 있습니다. 같은 프로토타입을 이용하여 생성된 park과 kim 객체는 getType() 을 사용할 수 있습니다.


테스트를 한번 해보면



모두 getType()의 return 값인 대학생이 출력됨을 확인할 수 있습니다.


여기서 알아두어야 할 것은 프로토타입 객체에 프로퍼티나 메서드를 추가, 수정, 삭제할 때는 함수 안의 prototype 프로퍼티를 사용해야 합니다. 하지만 프로토타입 프로퍼티나 메서드를 읽을 때는 함수 안의 프로토타입 프로퍼티 또는 객체 이름으로 접근합니다.



소스에서 park 객체를 사용하여 getType() 리턴 값을 취준생으로 변경했습니다. 그리고 park과 kim에서 각각 getType()을 호출하면 park 객체를 사용해서 호출한 결과는 취준생으로 출력되고, kim로 호출한 결과는 대학생이 출력됩니다. 생성된 객체를 사용하여 프로토타입 객체의 메서드를 수정하면 프로토타입 객체에 있는 메서드를 수정하는 것이 아니라 자신의 객체에 메서드를 추가하는 것입니다. 쉽게 이야기해서 같은 이름의 getType()이면 자신의 객체에 가장 근접한 getType으로 덮는다고 생각하시면 됩니다. 변수 스코프를 생각하시면 이해하시기 편할겁니다. 변수를 사용할 때 전역변수와 지역변수가 있으면 자신과 가장 가까운 지역변수를 참조하는 것이 일반적인 방식입니다. 이 부분도 이런식으로 이해하시면 됩니다. 자신과 가장 가까운 객체 자기 자신 안에 getType을 정의함으로써 참조하던 getType 메소드를 사용하지 않고, 자신이 정의한 getType() 를 사용하는 겁니다.


위의 말을 좀더 쉽게 그림으로 풀어봤습니다 ㅎㅎ


다음으론 kim.age에 26이라는 값을 할당한 것을 알 수 있습니다. 예전에 객체를 설명드릴 때 객체는 뭐라고 설명했을까요?


객체란 독립적인 주체라고 설명을 드렸습니다 ! 


kim.age ?

이걸 보시면 이렇게 생각하시면 됩니다. kim이라는 객체가 있는데 이 객체에서 age라는 프로퍼티를 독립적으로 정의하려고 하는구나~ 아 그 값이 26이네?

그럼 kim이라는 객체에 age라는 프로퍼티가 있고, 그 프로퍼티에는 26이라는 값이 할당이 되어있겠구나 ~ 라고 말이죠.


그렇다면 park이라는 객체에도 age가 정의가 되어있고, 26이라는 값이 할당이 되어 있을까요?


답은


undefined !

undefined !

undefined !

독립적인 객체 kim에만 age를 정의했을 뿐이지, park에는 정의를 안했기 때문에 undefined가 나오는 것입니다. 


쉽게 예를 들면, 부모님이 10만원씩 아이들에게 용돈으로 줬습니다. A라는 아이는 그 돈으로 키보드를 하나 구매했죠.


여기서 문제


A라는 아이가 구매한 키보드가 B라는 아이에게도 상속이 될까요?


당연히 상속이 안됩니다. 그래서 좀 전에 봤던 예제에서 park이라는 객체에 age가 정의되지 않는 이유를 쉽게 이해하실 수 있을겁니다.


결론을 내리면, 프로토타입 객체는 새로운 객체가 생성되기 위한 원형이 되는 객체입니다. 같은 원형으로 생성된 객체가 공통으로 참조하는 공간입니다. 프로토타입 객체의 속성들을 읽는 경우에는 객체 또는 함수의 프로토타입 프로퍼티를 통해 접근할 수 있습니다. 하지만 추가, 수정, 삭제는 함수의 프로토타입 속성을 통해 접근해야합니다.


자바스크립트에서 기본 데이터 타입을 제외한 모든 것이 객체입니다.


Number, String, Boolean, undefined, null


Object


객체가 만들어지기 위해서는 자신을 만드는 데 사용된 원형인 프로토타입 객체를 사용해서 객체를 만듭니다. 이때 만들어진 객체 안에 __proto__ 프로퍼티가 자신을 만들어낸 원형을 의미하는 프로토타입 객체를 참조하는 숨겨진 링크가 존재합니다. 이 숨겨진 링크를 프로토타입이라고 정의합니다.



이전 예시를 두고 다시 설명할게요. park과 kim 객체의 속성인 __proto__ 프로퍼티가 프로토타입 객체를 가리키는 숨은 링크가 프로토타입이라고 합니다. 


처음에 프로토타입을 크게 2 가지로 해석된다고 했죠?


함수의 속성인 프로토타입 프로퍼티는 프로토타입 객체를 참조하는 속성입니다.

그리고 함수와 new 연산자가 만나 생성한 객체의 프로토타입 객체를 지정해주는 역할을 합니다.

객체 안의 __proto__ 프로퍼티는 자신을 만들어낸 원형인 프로토타입 객체를 참조하는 숨겨진 링크로써 프로토타입을 의미합니다.


자바스크립트에서는 숨겨진 이 __proto__ 링크가 존재하고 있어 프로토타입 객체 속성에 접근할 수 있습니다. 그래서 이 프로토타입 링크를 사용자가 정의한 객체에 링크가 참조되도록 설정하면 코드의 재사용과 객체 지향적인 프로그래밍을 할 수 있습니다.

728x90
반응형
그리드형

💖 저자에게 암호화폐로 후원하기 💖

아이콘을 클릭하면 지갑 주소가자동으로 복사됩니다