[TIL]200909 Prototype Chain

Chaegyeom·2020년 9월 9일
0

TIL

목록 보기
31/77
post-thumbnail

오늘은 OOP와 Prototype Chain에 대해서 배우는 날인데 더 명확하게 알고싶어서 찾다보면 더 원론적인 부분으로 빠지고 명확했던 것 조차 명확해지지 않은 느낌이 드는 내용들이 많아서 우선 지금 명확한 부분만이라도 정리하고자 한다.

Prototype?

객체지향언어(Java, Python 등)에서 클래스(Class)라는 개념은 빠질 수 없는 개념이다. 그런데 객체지향언어인 자바스크립트에서는 클래스라는 개념이 없고 대신 프로토타입(Prototype)이라는게 존재한다. 이 프로토타입의 존재로 인해 자바스크립트가 프로토타입 기반 언어라고 불린다.

프로토타입이란 무엇일까?

사전적인 의미를 보면 Prototype이란 원형(原型)이고
原型이란 제작물의 근본이 되는 거푸집 또는 본보기이다.

자바스크립트에서 프로토타입이란 말 그대로 객체의 원형이라고 할 수 있다.
지난 포스트에 작성한 바와 같이 함수는 일급'객체'이다(객체다). 그러므로 생성자로 사용될 함수도 객체라고 할 수 있다.

그리고 객체에서 prototype이라는 프로퍼티(속성)은 용도가 약속되어 있는 프로퍼티이다. prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질때 그 객체에 연결된다.

자바스크립트의 모든 객체는 부모를 가지고 있는데 이 때 부모객체를 프로토타입 객체(프로토타입(prototype)이라고도 한다)라고 한다. 이것을 통해 객체지향 프로그래밍의 상속(Inheritance)개념과 같이 부모객체의 속성(property)과 메소드(method)를 사용할 수 있다.

Prototype Object

함수를 정의하게 되면 해당함수에 constructor(생성자)자격을 부여하고 해당함수의 Prototype Object를 생성하고 연결하는 두가지 작업이 이루어진다.

  • constructor자격이 부여되면 new키워드를 통해 객체를 생성할 수 있게 된다.

    생성자(constructor)가 아니면(함수가 아니면) new키워드를 통해 객체를 생성할 수 없다.

    함수를 정의하게 되면 해당함수에 constructor자격이 부여되기 때문에 new키워드를 쓸 수 있다.
  • 해당함수의 Prototype Object를 생성하고 연결한다.
    함수를 정의하게되면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성되게 된다. Prototype Object는 일반적인 객체와 같고, 기본적으로 constructor__proto__를 가지고 있다.

    constructor는 생성자 함수 자체를 가리키고
    __proto__Prototype Link이다.

Prototype Object는 일반적인 객체이므로 속성을 추가/삭제할 수 있다.(assignable하다고 한다)
예를 들자면 Human은 잠을 자니까 잠을 잔다는 속성을 추가하고 싶다면

이렇게 할 수 있다. 그리고 new키워드를 통해 생성된 객체는 Human.prototype을 참조할 수 있게 된다.

haebae라는 객체에 sleep이라는 속성은 없으나 new키워드를 통해 Human을 참조하여 생성되었기 때문에 Human의 속성을 참조하게 된다.

haebae에는 sleep이라는 속성이 없는데 Zzz가 찍히는 것은 Prototype Object에 존재하는 sleep이라는 속성을 참조한 것인데 이것은 haebae객체가 가지고 있는 __proto__속성에 의해 가능해진다.

prototype속성은 함수만 가지고 있던 것과는 달리 __proto__속성은 모든 객체가 가지고 있는 속성인데 __proto__은 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킨다.

new키워드를 통해 Human을 참조하여 생성된 haebae는 Human함수의 Prototype Object를 가리킨다.

haebae객체가 sleep 속성을 가지고있지 않기 때문에 sleep속성을 찾을 때 까지 상위 프로토타입을 탐색하고 최상위인 Object의 Prototype Object까지 찾았는데도 없는 경우 undefinde를 리턴한다.

이렇게 __proto__속성을 통해 상위 프로토타입과 연결되어 있는 형태를 프로토타입체인(Prototype Chain)이라고 한다.

Object.create


사람인 haebae는 잘 수 있다.

개미는 배우고있다.

그런데 사람인 개미도(개미라는 이름의 학생이다) 잘수 있는 것 아니겠는가?

__proto__을 .prototype로 할당

개미의__proto__속성을 Human.prototype으로 할당하면 어떨까?

갑자기 개미가 배우지 못하게 되었다....

prototype을 묶는다


Human과 Student의 프로토타입을 연결시켰더니
개미는 잠도자고 배우기도한다. 하지만 Human은 아직 배우게 하지 않았는데 배우게 되었다...
객체의 참조를 바꿔버렸기 때문에 Human에도 learn이 생기게 되었다.

prototype을 복사한다


Object.create메소드를 통해 Student에 Human의 prototype을 복사해왔다. 그리고 learn을 가르치니 개미는 공부도하고 잠도자지만 Human은 아직 배우지는 못하는 내가 원하는 상황을 만들었다.

그런데 constructor가 조금 이상하다?

원래는 생성자 함수 자체를 가리키던 constructor가 Human으로 바뀌어 버렸다. 이찜찜함을 해결하기 위해서는


Object.create를 통해 Student로 복사된 Human의 prototype중에서 constructor를 다시 Student로 바꿔주면 해결된다.

자바스크립트에서 상속을 구현하기 위해 이렇게 힘든방법을 쓰는게 안쓰러웠는지
ES6부터는 class문법이 추가되었다.

위에서 열심히 Object.create로 복사하고 constructor를 재할당 해준것을 간단하게 할 수 있게 되었다. class문법으로 위 상황을 다시 짜봤다

Human은 잠만 자고 Student는 잠도자고 배우기도 한다. 또한 Student의 constructor도 문제가 없는 것이 보인다.

자 이제 말을 시켜보자

Human prototype을 가진 haebae는 사람이라고 말한다. Student prototype을 가진 개미가 학생이라고 말하는데 개미는 사람이기도 하니 사람이라고도 말했으면 좋겠다

이럴 때 쓸 수 있는 것이 super키워드다 super키워드를 써보면 아래와 같다

개미가 사람이면서 학생이라고 말하고 있다.

super 키워드

서브 클래스와 슈퍼 클래스에 같은 이름의 method가 존재하면 슈퍼 클래스의 메서드는 호출되지 않는데, 이때 super 키워드를 사용해서 슈퍼 클래스의 method를 호출할 수 있다.

profile
주니어 개발자가 되고싶은

0개의 댓글