Codestates SEB FE 42기/정리노트

S2 unit2 | 프로토타입 체인, 최상위요소는 무엇일까?

2realzoo 2022. 11. 23. 12:35

📌 프로토타입 상속

: 넓은 범위의 클래스를 좁은 범위의 클래스에 상속할 수 있다.

✔ extends

: 클래스를 다른 클래스의 자식으로 만들기 위해 class 선언, class 식에 사용됨 🔗

 class ChildClass extends ParentClass { ... }

 

✔ super

: 부모 클래스의 생성자 함수를 호출하기 위해 사용됨 🔗

super([arguments]); // 부모 생성자 호출
super.functionOnParent([arguments]); // 부모 메서드만 따로 호출 가능

1. this 나오기 전에 사용 => Reference 에러

  1. 생성자 함수 내에선 한번만 사용 가능
  2. 정적 메서드(static) 도 호출 가능
class Human {
  constructor() {}
  static ping() {
    return 'ping';
  }
}

class Computer extends Human {
  constructor() {}
  static pingpong() {
    return super.ping() + ' pong';
  }
}
Computer.pingpong(); // 'ping pong'

4. super() 작성하지 않으면 생성자에 기본으로 super()가 생성됨 => 자식 클래스가 부모 클래스 속성, 메서드를 상속받음

5. super()로 부모 속성을 삭제할 시 reference 오류 생성

class Base {
  constructor() {}
  foo() {}
}
class Derived {
  constructor() {}
  delete() {
    delete super.foo;
  }
}

new Derived().delete(); // 참조오류: 'super'와 관련된 삭제가 유효하지 않습니다.

6. non-writable 속성 덮어쓸 수 없음

예를 들어 Object.defineProperty로 속성을 정의할 때, super의 속성 값을 덮어 쓸 수 없다.

class X {
  constructor() {
    Object.defineProperty(this, "prop", {
      configurable: true,
      writable: false,
      value: 1
    });
  }
  f() {
    super.prop = 2;
  }
}

var x = new X();
x.f();
console.log(x.prop); // 1

7. 객체 리터럴에서도 사용할 수 있음

Object.setPrototypeOf()로 obj2 prototype에 obj1을 세팅

var obj1 = {
  method1() {
    console.log("method 1");
  }
}

var obj2 = {
  method2() {
   super.method1();
  }
}

Object.setPrototypeOf(obj2, obj1);
obj2.method2(); // logs "method 1"

상속 예시

Human 클래스

class Human {
    constructor(name, age, gender){
        this.name = nmae;
        this.age = age;
        this.gender = gender;
        }
    eat(){
        console.log(`${name}가 밥을 먹었습니다.`)
        }
    sleep(){
        console.log(`${name}가 잠을 잡니다.`)
        }
    }

Student는 Human의 부분집합이므로, 클래스를 상속하여 재사용할 수 있다.

class Student extends Human {
    constructor(name, age, gender, grade){
        super(name, age, gender) //super키워드로 부모 클래스의 생성자 함수 호출
        this.grade = grade;
        }
    study(){
        console.log(`${name}이 공부를 시작합니다.`)
        }
    }

extends와 super 키워드를 사용하여 Student 클래스가 Human의 메서드와 속성을 물려받게 한다.

추가로 다른 메서드와 속성을 넣을 수 있다.

 


오버라이딩

: 부모 클래스에서 이미 정의된 함수 등을 자식 클래스에서 같은 이름으로 사용하되, 내부 기능이나 속성을 바꾸어 사용

class Student extends Human {
    constructor(name, age, gender, grade){
        super(name, age, gender) //super키워드로 부모 클래스의 생성자 함수 호출
        this.grade = grade;
        }
    study(){
        console.log(`${name}이 공부를 시작합니다.`)
        }
    sleep(){
        if(age === 19){
            console.log(`고삼은 많이 잘 수 없었습니다.`)
            }
        else {
            console.log(`${name}가 잠을 잡니다.`)
            }
    }

🔗메서드 오버라이딩

 


📌 DOM 프로토타입

DOM은 트리구조로 이루어져있으며 하나의 부모에 여러 개의 자식 요소가 달린 구조로 이루어져 있다.

=> 부모 클래스와 자식 클래스 존재

🔗Object

🔗EventTarget

🔗Window

🔗Node

🔗Document

🔗Element

div의 __proto__는 HTMLDivElement 클래스이다.

계속 거슬러가다보면 EventTarget 클래스가 나오게 된다.

EventTarget의 윗 클래스는 이름이 나오지 않았고 그 위는 null이 나온 것으로 보아 이게 root라는 걸 알 수 있었다.

EventTarget.__proto__ 하면 바로 나올 줄 알았지만 이렇게 익명함수가 나왔다.

EventTarget.__proto__.__proto__를 하니 그제서야 Object가 나온다.

이유가 뭘까...?

위에서 거슬러 올라갔던 프로토타입과 같은지 확인했더니 맨 마지막 체인이 Object와 같음에 true를 반환했다.

그래서 확인해보니 constructor에 Object()라고 적혀있다.

✔ 궁금한 점

1. EventTarget.__proto__에 Object가 아니라 익명함수가 나오는 이유 => 

이유는 알 수 없었지만 실시간 세션 때 동기 분이 알려주신 힌트...! 

아마 div로 들어가는 구조랑 EventTarget으로 바로 들어가는 구조가 달라서 그런 것 같다.

 

2. Window의 하위요소로 Document가 있다고 하는데, Document.__proto__는 Node이다.

부모는 하나만 가질 수 있는 게 아니었나...?

>> 콘솔창에 Window.document 해본 결과 undefined가 떴다.

여기서의 document는 다른 건가 싶다.

🔗Window.document