안녕하세요. 오늘은 자바스크립트(javascript)의 "클래스(class)"에 대해 알아보겠습니다.
자바스크립트는 prototype 기반의 언어이나 ES6부터 class라는 개념이 추가로 도입되었습니다.
* 상속, prototype의 개념을 알아야 클래스를 이해할 수 있으므로,
상속을 처음 보시는 분들은 아래 포스팅을 참조하시기 바랍니다! *
🩶- 상속, 프로토타입 포스팅 보러가기 -
[javascript] 상속, 프로토타입(prototype) (tistory.com)
prototype 기반의 코드와 class 기반의 코드는 상속의 기능적 측면에서 큰 차이는 없으나, class 기반으로 작성된 코드가 보다 더 직관적이며 가독성이 높습니다.
📍 class란 무엇인가 ❔
→ 클래스는 객체를 생성하기 위한 템플릿입니다.
Q. 잠깐, 객체를 생성하기 위한 템플릿은 "생성자 함수" 아니었나요?
A. 맞습니다! 생성자함수와 클래스는 둘 다 객체를 생성하기 위한 템플릿의 용도입니다. 다만 생성자 함수의 경우 저번 포스팅에서 다루었듯 프로토타입 기반의 코드를 통해 상속이 이루어졌죠. 오늘은 클래스를 통한 상속을 살펴볼겁니다. 클래스는 어떻게 생겼고, 어떤 방식으로 객체를 생성할까요?

🚨 클래스 (class) 🚨
📘🖍️
1. 클래스도 생성자 함수와 마찬가지로 이름의 첫 글자는 대문자여야 합니다.
2. 클래스는 클래스 내부에 <생성자 메소드>를 둡니다. 이 <생성자 메소드(constructor)>가 객체를 생성해주는 역할을 합니다.
3. 생성자 함수 내에 있는 메소드는 생성자 함수의 소속이었지만, 클래스 내에 존재하는 메소드는 클래스의 프로토타입으로부터 상속받은 메소드입니다.
4. for...in 구문은 본인의 속성들 뿐만 아니라 상속받은 속성들도 읽어내는 구문이라고 지난시간에 언급드렸지만, 유일하게 클래스로부터 상속받은 속성이나 메소드들만은 인식해내지 못합니다.
📘🖍️
🌳 # 클래스 사이의 상속 🌳
→ 키워드 "extends"를 통해 이루어집니다.
→ 기본적으로 자식 클래스는 부모 클래스의 모든 것을 상속받게 됩니다.
설령 자식 클래스 내부가 텅 비어있더라도 관계없이 자식 클래스에서 부모 클래스의 모든 것을 참조할 수 있습니다.
코드를 살펴보겠습니다.

class Bmw extends Car 🚗
→ Bmw 클래스는 Car 클래스에게 상속받는다
→ Car 클래스는 부모 클래스, Bmw 클래스는 자식 클래스이다.
부모클래스 Car에는 생성자 메소드 constructor와 함수 2개가, 자식클래스 Bmw에는 go 함수 하나만이 존재하고 있습니다. 클래스의 메소드는 클래스 소속이 아닌, 클래스의 프로토타입 소속이라는 거 기억하시나요? 그러므로 go함수는 Car 클래스 소속이며, drive함수와 stop함수는 Car 클래스의 프로토타입의 소속 메소드입니다. 프로토타입 체인에 의해 Bmw 클래스로부터 만들어진 객체 인스턴스는 Car 클래스의 모든 것, 나아가 Car 클래스 프로토타입의 모든 것까지 참조할 수가 있습니다. 따라서 코드의 후반부에 생성된 mycar 객체를 통해 drive, stop, go함수 모두 호출할 수 있게 됩니다.
속성도 마찬가지의 메커니즘을 통해 상속되므로, Bmw 클래스가 생성한 객체 인스턴스 mycar는 color,wheel 속성을 갖습니다.
✔️ “super” 키워드의 두 가지 용도 ✌🏻
1. 부모 클래스의 생성자를 호출
- 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출할 수 있다.
2. 부모 클래스의 메소드를 호출
- 이렇게 하면 자식 클래스에서 부모 클래스의 메소드를 오버라이딩 한 경우에도 부모 클래스의 메소드를 호출할 수 있다.
**********
☝🏻1️⃣ 부모 클래스의 생성자를 호출
자식 클래스에 생성자 메소드가 없을 때에는 당연히 부모 클래스로부터 부모의 생성자 메소드가 자동으로 상속됩니다. 하지만 자식 클래스에 만약 constructor 메소드의 틀이 존재할 경우에는 이야기가 달라집니다. 이 경우는 constructor 메소드 내에서 다시 부모 클래스의 생성자를 호출하여 상속받아야 합니다. “super” 키워드를 사용해서 말이죠. 아래의 코드를 봅시다.

위 코드의 자식 클래스 Mimi는 constructor 틀을 가졌기 때문에 무조건적으로 "super"키워드를 통해 부모 생성자를 상속받는 과정을 거쳐야 합니다. 그런데 왜 그냥 super()가 아니라 괄호 안에 name 변수를 넣어준 걸까요? const bbibbi = new Mimi("삐삐");를 통해 bbibbi객체의 name속성인 "삐삐"가 자식 클래스 Mimi에게 전달되는 것 보이시나요? 자식 클래스에 전달된 이 name속성을 자식 클래스가 부모 클래스에게 전달해 주어야 하기 때문에(자식 클래스에는 현재 this.name할당과정이 없으므로) 이 경우 constructor(name) / super(name) 괄호 안에 모두 name 변수를 기재해야만 합니다. Mimi 클래스는 부모 클래스에게 부모 생성자를 호출해야 생성자를 상속받을 수 있으므로, 부모 생성자를 호출할 때 name매개변수를 함께 넣어 전달 보내는 것입니다.
✌🏻2️⃣ 부모 클래스의 메소드를 호출
# 메소드 오버라이딩
만약 자식 클래스가 부모 클래스가 가진 메소드와 똑같은 이름의 메소드를 가진다면 어떻게 될까요?
프로토타입 체인에 의하면 자식 클래스는 본인의 내부를 가장 먼저 들여다보고 그 안에서 원하는 것을 찾을 수 없으면 그 때 부모 클래스로 거슬러 올라가는 메커니즘이 재귀적으로 이루어집니다. 그런데 호출한 함수가 이미 자식 클래스 본인 내부에 있다면, 굳이 부모 클래스를 참조할 필요가 없겠죠. 따라서 부모 클래스로부터 상속받은 메소드는 자식 클래스에서 정의된 새로운 메소드에게 덮어지게 되고, 이를 "메소드 오버라이딩" 이라고 합니다.
부모에게 상속도 받고 추가적으로 자식의 값도 사용하고 싶을 때 "super"키워드를 사용하여 부모 클래스의 메소드를 호출하게 됩니다.

Dog 클래스에서 speak함수를 위 코드와 같이 정의하면, 부모 클래스에서 상속받은 speak 메소드가 먼저 출력된 후 자식의 오버라이딩 speak 메소드도 이어서 출력됩니다.
오늘은 클래스(class) 에 대해 알아보았습니다.
읽어주셔서 감사합니다.
오늘도 좋은 하루 보내세요 ! 🌟
'javascript' 카테고리의 다른 글
[javascript] 클로저(closure) (3) | 2024.03.11 |
---|---|
[javascript] 비동기 처리(callback, Promise) (3) | 2024.03.08 |
[javascript] 상속, 프로토타입(prototype) (30) | 2024.03.03 |
[javascript] 유용한 배열 메소드 (array method) 총정리 (25) | 2024.03.03 |
[javascript] 나머지 매개변수 (rest parameter) (1) | 2024.03.02 |