자바스크립트 완벽가이드 9장에 해당하는 부분이고, 읽으면서 자바스크립트에 대해 새롭게 알게된 부분만 정리한 내용입니다.
자바스크립트 클래스의 프로토타입 기반 상속 메커니즘이 자바나 그 비슷한 언어의 클래스 기반 상속 메커니즘과 상당히 다르다는 점을 이해해야 한다.
class 문법이 등장하기 이전, 자바스크립트 클래스를 정의할 수 있는 방법이 있었다.
Object.create()
를 활용한 방법각각을 코드로 한번 알아보자.
Object.create()를 활용하여 팩토리 함수로 프로토타입 상속하는 객체 생성
// Range 객체를 반환하는 팩토리 함수
function range(from, to) {
// Object.create()를 써서 아래에서 정의하는 프로토타입 객체를 상속한다.
let r = Object.create(range.methods);
r.from = from;
r.to = to;
// 마지막으로 새 객체를 반환
return r;
}
// 이 프로토타입 객체는 Range 객체가 상속하는 메서드 정의
range.methods = {
includes(x) { return this.from <= x && x <= this.to;}
// 클래스 인스턴스를 이터러블로 만드는 제너레이터 함수
// 이 기능은 숫자 범위에서만 동작
*[Symbol.iterator]() {
for(let x = Math.ceil(this.from); x<=this.to; x++) yield x;
}
toString() { return "(" + this.from + "..." + this.to + ")";}
}
let r = range(1, 3); // Range 객체 생성
r.includes(2); // true
r.toString(); // "(1...3)"
Object.create()
를 활용해 프로토타입을 상속하고, 초기화된 객체를 반환해주는 형식으로 클래스 생성
생성자를 사용한 클래스
function Range(from, to) {
this.from = from;
this.to = to;
}
Range.prototype = {
includes(x) {
return this.from <= x && x <= this.to;
},
*[Symbol.iterator]() {
for (let x = Math.ceil(this.from); x <= this.to; x++) yield x;
},
toString() {
return '(' + this.from + '...' + this.to + ')';
}
};
const r = new Range(1, 3);
console.log(r.includes(2)); // true
console.log(r.toString()); // (1...3)
console.log([...r]); // [1, 2, 3]
생성자라는 것을 강조하기 위해
range -> Range
라는 이름을 사용. 또한 생성자로 만들어 객체를 반환한 필요 없음
class 키워드를 사용해 만든 Range 클래스
class Range {
constructor(from, to) {
this.from = from;
this.to = to;
}
includes(x) {
return this.from <= x && x <= this.to;
}
*[Symbol.iterator]() {
for (let x = Math.ceil(this.from); x <= this.to; x++) yield x;
}
toString() {
return '(' + this.from + '...' + this.to + ')';
}
}
const r = new Range(1, 3);
console.log(r.includes(2)); // true
console.log(r.toString()); // (1...3)
console.log([...r]); // [1, 2, 3]
Range 클래스의 서브 클래스인 Span을 만드는 코드
function Span(start, span) {
if (span >= 0) {
this.from = start;
this.to = start + span;
} else {
this.to = start;
this.from = start + span;
}
}
// Span 프로토타입은 Range 프로토타입 상속
Span.prototype = Object.create(Range.prototype);
// Range.prototype.constructor는 상속하지 않으므로 생성자 프로퍼티는 따로 정의
Span.prototype.constructor = Span;
Span.prototype.toString = function () {
return `(${this.from} ... + ${this.to - this.from})`;
};
위 코드가 자바스크립트에서 서브클래스가 동작하는 방식이며 ES6에서는 class 문법에
super
와extends
가 등장하면서 쉽게 서브클래스를 만들 수 있다.