JavaScript는 프로토타입 기반 언어로 프로토타입 체인을 사용하여 객체 지향 프로그래밍의 특성 중 상속을 구현한다.
예시를 들기 위해 학생(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다. Student는 Human의 특징을 그대로 물려받는다. 이렇게 속성과 메서드를 물려주는 클래스를 부모 클래스(여기서는 Human), 속성과 메서드를 물려받는 클래스를 자식 클래스(여기서는 Student), 그리고 이 과정을 상속이라고 한다.
extends와 super
자바스크립트에서는 extends 와 super 키워드를 이용해서 상속을 구현할 수 있다.
class Human {
constructor(name, age){
this.name = name;
this.age = age;
}
sleep(){ return `${this.name}이(가) 잠을 잡니다.`}
}
class Student extends Human{
constructor(name, age, grade){
super(name, age);
this.grade = grade;
}
study(num){
this.grade = this.grade + num;
return `${this.name}의 성적이 ${num}만큼 올라 ${this.grade}이 되었습니다.`
}
}
여기서 Student는 extends 키워드를 이용하여 Human 클래스를 상속한다. 따라서 부모 클래스는 Human이고 자식 클래스는 Student이다.
super 키워드는 부모 클래스의 함수를 호출할 때 사용된다. (생성자 함수 내에서 쓰일 때, super 는 한번만 사용될 수 있음)
this 키워드가 사용되기 전에 사용되어야 하며, 그렇지 않을 경우 Reference 에러가 난다.
생성자 함수 내에서 super를 호출하면 부모 클래스의 생성자 함수를 호출한다.
사용 예시
class Human {
constructor(name, age){
this.name = name;
this.age = age;
}
sleep(){ return `${this.name}이(가) 잠을 잡니다.`}
}
class Student extends Human{
constructor(name, age, grade){
super(name, age);
this.grade = grade;
}
study(num){
this.grade = this.grade + num;
return `${this.name}의 성적이 ${num}만큼 올라 ${this.grade}이 되었습니다.`
}
}
class ForeignStudent extends Student{
constructor(name, age, grade, country){
super(name, age, grade);
this.country = country;
}
speak(){
return `${this.country} 언어로 수업을 진행합니다.`
}
}
let americanStudent = new ForeignStudent('jake', 23, 80, '미국');
참고할 만한 문서
- JavaScript에서의 상속 중 "ECMAScript 2015 클래스"
- https://learnjs.vlpt.us/basics/10-prototype-class.html
DOM과 프로토타입
브라우저에서 DOM을 이용하면, document.createElement('div')로 새로운 div 엘리먼트를 만들 수 있다. 이렇게 생성된 div 엘리먼트는, HTMLDivElement라는 클래스의 인스턴스이다.
DOM 엘리먼트는 예를 들어 innerHTML과 같은 속성, 또는 append()와 같은 메서드가 있다. 각각의 엘리먼트가 해당 메서드나 속성이 있다는 것을 통해, Element라는 공통의 부모가 있음을 알 수 있다. 즉, DOM도 상속관계로 이루어져있음을 알 수 있다.
화살표 방향은 부모를 가리키며, EventTarget의 부모로는, 모든 클래스의 조상인 Object가 존재한다.
참고로 node의 유형은 Node.nodeType 속성을 이용하여 구분할 수 있는데 목록은 다음과 같다. (element 포함)
Node.ELEMENT_NODE
Node.ATTRIBUTE_NODE
Node.TEXT_NODE
Node.CDATA_SECTION_NODE
Node.PROCESSING_INSTRUCTION_NODE
Node.COMMENT_NODE
Node.DOCUMENT_NODE
Node.DOCUMENT_TYPE_NODE
Node.DOCUMENT_FRAGMENT_NODE
EventTarget의 prototype
let div = document.createElement('div');
document.body.append(div);
div.textContent = '몰입의 즐거움을 느낄 수 있습니다.';
div.addEventListener('click', () => console.log('몰입을 하면 놀라운 일이 생깁니다.'));
- EventTarget의 prototype에는 addEventListener() 메서드가 있다.
- div는 HTMLDivElement의 인스턴스이고 EventTarget을 상속받았기 때문에 addEventListener()를 사용할 수 있다.
- 보통 클래스의 인스턴스는 new 키워드로 생성하지만, DOM에서는 new 키워드가 아닌 createElement()를 사용한다.
__proto__ 를 이용한 상속 관계 탐색하기
인스턴스의 __proto__를 이용하면 이를 더 확실하게 확인할 수 있다. __proto__를 이용하면 부모 클래스의 프로토타입, 혹은 '부모의 부모 클래스'의 프로토타입을 탐색할 수 있다.
__proto__를 이용하여 프로토타입 체인의 과정을 콘솔로 찍어보았다.
let div = document.createElement('div');
div.__proto__
div.__proto__.__proto__
div.__proto__.__proto__.__proto__
div.__proto__.__proto__.__proto__.__proto__
div.__proto__.__proto__.__proto__.__proto__.__proto__
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__
div.__proto__
HTMLDivElement
div.__proto__.__proto__
HTMLElement
div.__proto__.__proto__.__proto__
Element
div.__proto__.__proto__.__proto__.__proto__
Node
div.__proto__.__proto__.__proto__.__proto__.__proto__
EventTarget
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__
Object (여기가 끝!!)
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__
null
한눈에 보기
이상으로 __proto__를 활용하여 상속 관계를 확인해보았다.
'FE > JavaScript' 카테고리의 다른 글
[JS] 비동기 코드 제어하기 : callback / promise / async, await (0) | 2023.03.20 |
---|---|
[JS] 비동기 흐름 : 배열 메서드 구현해보기 (Underbar) - 하 (0) | 2023.03.19 |
[JS] 객체 지향 프로그래밍(OOP)의 4가지 주요 개념 (0) | 2023.03.15 |
[JS] 객체 지향 프로그래밍 - 클래스와 인스턴스 (0) | 2023.03.15 |
[JS] 추상화 ** (0) | 2023.03.14 |