본문 바로가기
My Wiki (CodesStates)/JS,Node

(5-3) JS/객체 지향 JavaScript/클래스와 프로토타입

by Esoolgnah 2021. 8. 23.
728x90

 

JavaScript는 프로토타입 기반 언어이다.

여기서 프로토타입(Prototype)은 원형 객체를 의미한다. 프로토타입 문서를 반드시 읽어 보자.
다음과 같이 Human이라는 클래스를 구현해 본다. 개발자 도구를 열어 다음 코드를 실습해 보자.

class Human {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sleep() {
    console.log(`${this.name}은 잠에 들었습니다`);
  }
}

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

// 실습해보세요
Human.prototype.constructor === Human; // 결과는 무엇일까요?
Human.prototype === kimcoding.__proto__; // 결과는 무엇일까요?
Human.prototype.sleep === kimcoding.sleep; // 결과는 무엇일까요?

[코드] OOP 패턴으로 구현한 Human 예시

 

 

 

다음 그림은 반드시 기억하자.

Human이라는 클래스와 인스턴스, 그리고 프로토타입의 관계

 

[그림] 클래스 Human과 인스턴스, 그리고 프로토타입의 관계 모식도

 

 

 

우리가 흔히 쓰는 배열 역시 원리가 동일하다. 배열을 Array 클래스의 인스턴스로 생각할 수 있고 프로토타입에 다양한 메소드가 존재한다.

 

 

 

 

Array(배열) 클래스와 인스턴스, 그리고 프로토타입의 관계

 

[그림] 배열 arr과 Array, 프로토타입의 관계 모식도

 

 

 

프로토타입 체인

객체 지향 프로그래밍의 특성 중 "상속"을 JavaScript에서 구현할 때에는 프로토타입 체인을 사용한다. 예시를 들기 위해 학생(Student)과 사람(Human)이라는 클래스가 각각 존재한다고 가정하겠다. 클래스 Human의 메소드와 속성을 객체로 구현한다면 다음과 같다.

 

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

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

[코드] 클래스 Human의 속성과 메소드 예시

 

 

 

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

 

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

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

[코드] 클래스 Student의 속성과 메소드 예시

 

 

 

위 예시에서 나타나는 박해커(parkhacker) 씨는 Student이다. 박해커 씨가 학생이라고 해서 age나 gender와 같은 속성이 존재하지 않거나 sleep() 이나 eat() 이라는 메소드를 사용할 수 없을까? 그렇지 않다. Student는 Human의 특징을 그대로 물려받는다. 이렇게 속성과 메소드를 물려주는 클래스를 부모 클래스(여기서는 Human), 속성과 메소드를 물려받는 클래스를 자식 클래스(여기서는 Student), 그리고 이 과정을 상속이라고 한다.

자바스크립트에서는 extends 와 super 키워드를 이용해서 상속을 구현할 수 있다. 다음 문서 JavaScript에서의 상속 중 "ECMAScript 2015 클래스"를 읽어보자.

 

 

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

모든 DOM 엘리먼트는 textContent와 같은 속성, 또는 append()와 같은 메소드가 있다. 각각의 모든 엘리먼트가 해당 메소드나 속성이 있다는 것을 통해 Element라는 공통의 부모 클래스가 있음을 짐작할 수 있다. 따라서 MDN의 문서에서는 다음과 같이 상속 관계를 함께 표현한다.

 

[그림] div 엘리먼트의 클래스 모식도

 

 

화살표 방향은 부모 클래스를 가리킨다. EventTarget의 부모로는 모든 클래스의 조상인 Object가 존재한다. 개발자 도구를 사용하면 해당 메소드나 속성이 어떤 클래스로부터 비롯되었는지 확인할 수 있다.

 

[그림] 개발자 도구에서 어떤 클래스로부터 비롯되었는지 확인할 수 있다.

 

 

위 그림에서 확인할 수 있듯이 innerText 속성은 HTMLElement로부터, textContent 속성은 Node로부터 비롯되었다. 인스턴스의 __proto__를 이용하면, 이를 더 확실하게 확인할 수 있다. __proto__를 이용하면 부모 클래스의 프로토타입, 혹은 '부모의 부모 클래스'의 프로토타입을 탐색할 수 있다.

 

 

질문

  • addEventListener 속성은 어떤 클래스의 프로토타입에서 찾을 수 있을까?
  • remove 메소드는 어떤 클래스의 프로토타입에서 찾을 수 있을까?
  • 모든 객체에 toString() 메소드가 존재하는 이유가 무엇일까?

 

 

 

 

반응형

댓글