[자바스크립트] 프로토타입

2020. 3. 1. 16:52프로그래밍-Web/Javascript

듣고 싶은 강의가 있는데

클로져, this, 프로토타입

요 세가지는 정리를 하고 듣고 싶어서... 여기까지 정리한다 ㅠㅠ

 

1) 프로토타입

기본적인 구조는 이렇다.

new 키워드를 이용하여 생성자 함수를 통해 인스턴스를 생성하는 경우,

생성자 함수는 protoType라는 메소드를 가지고 있고,

인스턴스에 생성된 __ proto__가 이를 참조하게 된다.

 

즉 자바스크립트의 함수인 객체는 (거의 항상) protoType을 가지고 있고

(거의 모든) 객체는 항상 __proto__라는 프로퍼티가 존재한다.

위의 그림을 예시로 들어보자.

test()라는 함수객체를 생성하고, 이는 object객체를 참조한다(모든 객체 생성이 다 그렇다!)

test는 protoType이라는 메소드를 가지고 있게 되고, 

아래 새로 생성한 k라는 인스턴스는 test를,

k의 __proto__라는 프로퍼티는 test의 protoType을 참조하게 된다

그러므로 첫번째 콘솔은 true가, 두번째 콘솔은 test의 protoType에 저장된 b값 3이 출력되는 것.

 

또한 프로토타입 체인을 통해 최상단 protoType까지 스캔하기 때문에,

세번째 콘솔의 경우__proto__의 __proto__는 object객체의 prototype 속 c를 참조하여 4가 출력된다.

 

그리고 이 모든과정에서 __proto__는 생략하고 인스턴스와 같은 취급을 할 수 있다.

(그래서 보통 코드에 쓰지 않는다)

 

2) 프로토타입의 활용

 

그럼 이를 어디에 활용할 수 있을까?

공통인 protoType을 생성자 함수가 가지고 있으니, 

인스턴스를 생성할때마다 공통으로 사용되는 메소드나 객체를 그 안에 선언하는 방식으로 사용할 수 있다.

이 경우 crmRelease와 crmRelease2라는 각각의 객체가 생성자의 protoType 안에 있는 같은 set함수를 사용하고 있다.

 

3) 접근 가능한 메소드

 

이 그림에서 보듯, 생성자 함수에 해당하는 클래스는

자신들이 가지고 있는 method들이 있고, 그와 별개로 자신의 protoType안에 정의된 method들이 있다

하지만 인스턴스가 사용할 수 있는건 protoType에 정의된 메소드들 뿐이다.

예컨데 이런식이다.

Person에 바로 정의한 getInfo는 인스턴스가 사용할 수 없지만,

protoType에 구현해 둔 getAge나 getName은 사용 쌉가능이다.

 

4) 상속

 

이 protoType을 가장 유용하게 써먹을 수 있는 방안은 '상속'이다.

예시를 들어보자

만일 저렇게 두개의 객체가 존재한다고 해보자.

각각은 모두 get 메소드를 가지고 있다고 가정한다.

이러한 경우에 backback의 객체는 gihong의 객체 상위에 존재하게 된다.

따라서 getName과 getAge 메소드는 backback객체에,

gihong객체는 backback객체에 두고 getPosition 메소드를 정의하면 될 것이다.

즉, gihong과 backback을 상속관계로 정의하는 것이다.

 

그림이 좀 구리지만....

gihong.protoType이라는 인스턴스가 backback이라는 생성자 함수를 보고

그 아래 실제 gihong이라는 인스턴스가 gihong이라는 생성자 함수를 보는 식이다.

이 과정에서 일단 gihong의 protoType이 backback 생성자 함수의 인스턴스가 되었으므로

이러한 선언이 필요하다.

하지만 여기에서 주의할점은 gihong(마지막 인스턴스... 쓰다보니 이름이 중복된다 ㅠ)의 생성자가 gihong이라는 사실이다. 

그렇게 하지 않으면 gihong의 생성자가 backback 된다. 

잘나온다.

gihong이 backback을 상속하였다

하지만 이러한 경우 문제는,

gihong이 getPosition만 __proto__에 담는것이 아니라 age, name 참조를 gihong에서 한다는 것에 있다.

 

그래서 보통 이렇게 바로 연결해주지 않고 중간에 빈 객체인 브릿지를 이용한다.

요렇게 말이다.

이것의 활용성을 높이기 위해서 함수화를 해보자.

요렇게 한 후, name과 age는 항상 super부모를 참조하도록 선언해주면 된다.

 

+ 잠깐 즉시실행함수 체크

 

마지막으로 ES6에서 제공하는 extends 키워드로 더 간단히 해보자

상속뿐이 아니라 모든 파트를 리팩토링

(사실 처음부터 이렇게 하면 되는..)

 

대신 이러한 방식은 prototype에 담는게 아니기 때문에 콘솔에 함수까지 찍혀서 나온다.

class는 인스턴스를 만들떄마다 내부 메소드를 독립적으로 만들어내기 때문이다.

사실 요 단점때문에 뭔가 께름칙 하다.