자바스크립트는 prototype 기반 언어라서 '클래스' 및 '상속'개념이 존재하지 않지만 prototype을 기반으로 클래스와 비슷하게 동작하게끔 하는 다양한 기법들이 도입돼 왔다.
ES6에서 클래스가 도입됐지만, 역시나 prototype을 기반으로 한 것이기 때문에 자바스크립트에서 클래스 상속을 구현했다는 것은 결국 prototype chaining을 잘 연결한 것으로 이해하면 된다.
클래스(class)
:: 어떤 사물의 공통 속성을 모아 정의한 추상적인 개념
인스턴스(instance)
:: 클래스의 속성을 지니는 구체적 사례
프로토타입 메서드(prototype method)
:: 클래스의 prototype 내부에 정의된 메서드 / 인스턴스가 마치 자신의 것처럼 직접 호출할 수 있음
스태틱 메서드(static method)
:: 클래스(생성자 함수)에 직접 정의한 메서드 / 인스턴스가 직접 접근할 수 없음 / 클래스(생성자 함수)를 this로 지정해 직접 접근해야만 호출 가능
단순하게 말하면 클래스는 'object를 뽑는 기계'다. 비슷한 object를 많이 만들 일이 있으면 클래스를 생성해 사용하면 된다.
function 기계 () {
this.q = 'consume';
this.w = 'snowball';
}
const nunu = new 기계(); // 기계 {q: 'consume', w: 'snowball'}
this
는 새로 생성되는 object(인스턴스)를 가리킨다.
그러니까 this.q = 'consume' 은 새로 생성되는 object에 {q: 'consume'} 을 추가해달라는 의미인 것이다.
// ES5 생성자 함수
function 기계 (구멍) {
this.q = 구멍;
this.w = 'snowball';
}
const nunu = new 기계('consume'); // 기계 {q: 'consume', w: 'snowball'}
const garen = new 기계('strike'); // 기계 {q: 'strike', w: 'snowball'}
// ES6 클래스
class Hero {
constructor (구멍) {
this.q = 구멍;
this.w = 'snowball';
}
}
const nana = new Hero('hello'); // Hero {q: 'hello', w: 'snowball'}
// ES5 생성자 함수
function 기계 (구멍) {
this.q = 구멍;
this.w = 'snowball';
this.showQ = function () {
console.log(this.q);
}
}
const nunu = new 기계('consume'); // 기계 {
// q: 'consume',
// w: 'snowball',
// showQ: ƒ (), ➡️ ❗️객체 내부에 showQ 있음
// __proto__: { constructor: ƒ 기계() }
// }
// ES6 클래스
class Hero {
constructor (구멍) {
this.q = 구멍;
this.w = 'snowball';
}
showQ () {
console.log(this.q);
}
}
const nana = new Hero('hello'); // Hero {
// q: 'hello',
// w: 'snowball',
// __proto__: { constructor: ƒ Hero(), showQ: ƒ showQ() } ➡️ ❗️prototype 내부에 showQ 있음
// }
☝🏼 여기서 생성자 함수가 클래스와 동일하게 동작하도록 만들고 싶으면 아래와 같이 수정하면 된다.
// ES5 생성자 함수
function 기계 (구멍) {
this.q = 구멍;
this.w = 'snowball';
}
기계.prototype.showQ = function() {
console.log(this.q)
}
아래의 코드는 인스턴스를 만들고자 했는데 실수로 new를 생략하고 작성한 경우를 나타낸 것이다.
const nunu = 기계('consume'); // undefined(기계 함수에 return문이 없으므로) ➡️ 문제가 없다.
const nana = Hero('hello'); // TypeError ➡️ 클래스는 new 없이 실행할 수 없다❗️
분명 개발자가 실수한 코드지만 생성자 함수의 경우 문제 없이 작동해 에러를 즉시 알아차릴 수 없다.
반면에 클래스를 사용하면 즉각적으로 에러를 잡아낼 수 있어 더 효율적으로 작업할 수 있다는 이점이 있다.
생성자 함수는 prototype을 이용해 상속(엄밀히 말하면 상속은 아니지만)을 구현했었다.
클래스에서의 상속(instance 생성 아니고, class로 class를 만드는 것!)은 extends
키워드를 사용한다.
// ES6 클래스
class Car {
constructor(color) {
this.color = color;
this.wheels = 4;
}
stop() { // myCar의 prototype의 prototype에 stop이 있다❗️
console.log('STOP!');
}
}
class Hyundai extends Car {
park() { // myCar의 prototype에 park가 있다❗️
console.log('PARKING');
}
}
const myCar = new Hyundai('blue');
클래스에서는 super.
메서드로 부모 클래스에 정의된 메서드를 사용할 수 있다(자식 내부에 같은 이름의 메서드가 존재해도 오버라이딩(overriding) 되지 않고 부모껄 출력한다.).
// ES6 클래스
class Hyundai extends Car {
park() {
console.log('PARKING');
}
stop() {
super.stop(); // 'STOP!'
console.log('OFF') // 'OFF'
}
}
myCar.stop();
※ 참고 자료
코어 자바스크립트
객체지향 Class 문법 10분만에 이해시켜줌 (자바스크립트)
자바스크립트 중급 강좌 #15 클래스(Class)