Prototype Chain

왕지호·2022년 11월 21일
0

프로토타입 체인

객체 지향 프로그래밍의 특성 중 상속을 JavaScript에서 구현할 때에는 프로토타입 체인을 사용한다.

그럼 여기서 상속인란 무엇일까?
상속에는 두가지 상속이 있다!

속성 상속(mdn 참고)
자바스크립트 객체는 속성을 저장하는 동적인 "가방"과 (자기만의 속성이라고 부른다) 프로토타입 객체에 대한 링크를 가진다. 객체의 어떤 속성에 접근하려할 때 그 객체 자체 속성 뿐만 아니라 객체의 프로토타입, 그 프로토타입의 프로토타입 등 프로토타입 체인의 종단에 이를 때까지 그 속성을 탐색한다.

메소드 상속(mdn 참고)
자바스크립트에 "메소드"라는건 없다. 하지만 자바스크립트는 객체의 속성으로 함수를 지정할 수 있고 속성 값을 사용하듯 쓸 수 있다. 속성 값으로 지정한 함수의 상속 역시 위에서 본 속성의 상속과 동일하다. (단 위에서 언급한 "속성의 가려짐" 대신 "메소드 오버라이딩, method overriding" 라는 용어를 사용한다)

상속된 함수가 실행 될 때, this 라는 변수는 상속된 오브젝트를 가르킨다. 그 함수가 프로토타입의 속성으로 지정되었다고 해도 말이다.

즉, 속성과 메서드를 물려주는 클래스를 부모 클래스, 속성과 메서드를 물려받는 클래스를 자식 클래스, 그리고 이 과정을 상속이라고 한다.


그럼 예를 하나 들어보자!

학생(Student)과 사람(Human)이라는 클래스가 각각 존재한다고 가정해보자

클래스 Human의 메서드와 속성을 객체로 구현한다면, 다음과 같다

let kimcoding = new Human('김코딩', 30);

// 속성
kimcoding.age;
kimcoding.gender;
// 메서드
kimcoding.eat();
kimcoding.sleep();

학생은 학생이기 이전에, 사람. 따라서 클래스 Student는 Human의 기본적인 메서드를 상속받을 수 있다. 다만, 학생은 일반적인 사람의 특징에 추가적인 특징이 필요하다.

let parkhacker = new Student('박해커', 22);

// 속성
parkhacker.grade;
// 메서드
parkhacker.learn();

위 예시에서 나타나는 박해커(parkhacker)는 Student이다. 박해커 씨가 학생이라고 해서, age나 gender와 같은 속성이 존재하지 않거나, sleep() 이나 eat() 이라는 메서드를 사용할 수 없을까?

그렇지 않다!

Student는 Human의 특징을 그대로 물려받기 때문에 상속을 받는다.


자바스크립트에서는 extendssuper 키워드를 이용해서 상속을 구현할 수 있다.

extends
클래스의 자식 클래스를 생성할 때 사용

class World {
    constructor(nation){
        this.nation = nation;
    }

    whereRUFrom(){
        console.log(`I'm from ${this.nation}.`);
    }
}

class Asia extends World {
    constructor(nation){
        super(nation);
    }
    whereRUFrom(){
        console.log(`I live in ${this.nation}.`)
    }
}

let imfrom = new Asia('SouthKorea');
imfrom.whereRUFrom();
//"I live in SouthKorea."

super
부모 생성자를 호출

부모 생성자의 일이 끝난 후 부모가 해결하지 못하는 것은 자식 생성자가 하도록 하는 것이다.

이 super()이 없다면 중복이 될 것을 부모에게 가서 실행시키고 오는것이다.

위 예를 참고해보자...

World라는 클래스를 사용 하면서 거기서 더 부가적인 기능을 추가해서 이용하고 싶을 때 extends, 상속을 이용한다.

물론 World 클래스에서 다른 메소드를 넣을 수 있으나, 만일 저 코드가 내 코드가 아니거나 수정하면 참 곤란해지는 것 이라면, 신경쓸게 많아질 것이다.

때문에 어차피 겹치게 될 World의 생성자를 상속받고 나머지는 자식인 Asia의 whereRUFrom만 호출하여 결국 자식의 콘솔로그만 출력이 되는 것이다.

출처: [JavaScript] 상속 (extends, super())


DOM과 프로토타입

브라우저에서 DOM을 이용하면, document.createElement('div')로 새로운 div 엘리먼트를 만들 수 있다. 이렇게 생성된 div 엘리먼트는, HTMLDivElement라는 클래스의 인스턴스이다.

DOM 엘리먼트는 예를 들어 innerHTML과 같은 속성, 또는 append()와 같은 메서드가 있다.

각각의 엘리먼트가 해당 메서드나 속성이 있다는 것을 통해, Element라는 공통의 부모가 있음을 알 수 있다.

화살표 방향은 부모를 가리킨다. EventTarget의 부모로는, 모든 클래스의 조상인 Object가 존재한다.

인스턴스의 __proto__를 이용하면 이를 더 확실하게 확인할 수 있다. __proto__를 이용하면 부모 클래스의 프로토타입, 혹은 '부모의 부모 클래스'의 프로토타입을 탐색할 수 있다.


실습

마무리로 실습 하나!

다음 코드를 실행했을 때 차례대로 출력되는 결과로 옳은 것을 골라보자!

let div = document.createElement('div');

div.__proto__.__proto__
div.__proto__.__proto__.__proto__

답: HTMLElement, Element

DOM도 상속 관계로 이루어져있다. proto 를 활용하여 상속 관계를 확인할 수 있다.

profile
개발 공부하는 코린이!

0개의 댓글