자바스크립트 → <프로토타입> 기반 언어 → <상속> 이라는 개념이 존재하지 않음.
ES6 에 클래스 문법 추가됨
ES5 에서 클래스를 흉내내기 위한 구현 방식을 학습하는 것은 큰 의미가 있음
자바스크립트는 프로토타입 기반 언어임 따라서 클래스의 개념이 존재하지 않음. 프로토타입은 일반적인 관점에서 클래스와 비슷하게 해석할 수 있다.
생성자 함수 Array를 new 연산자와 함께 호출하면(const arrayInstance = new Array()) 인스턴스가 생성된다. 이때 Array를 일종의 클래스라고 생각하면, Array의 prototype 객체 내부 요소들이 인스턴스(Instance)에 '상속'된다고 볼 수 있음.
→ 하지만 이는 상속이 아닌 <프로토타입 체이닝>에 의한 참조이다.
→ Array 내부 프로퍼티들 중 prototype 프로퍼티를 제외한 나머지는 인스턴스에 상속(참조)되지 않음
자바스크립트에서는 인스턴스에서도 직접 메서드를 정의할수 있기 때문에 '인스턴스 메서드'라는 명칭은 프로토타입에서 정의한 메서드를 지칭하는지 인스턴스에 정의한 메서드를 지칭하는 것인지 혼란을 야기함.
→ 자바스크립트 커뮤니티에서는 인스턴스 메서드 대신 프로토타입 메서드라고 더 많이 사용함.
// 예제 7-1 스태틱 메서드, 프로토타입 메서드
var Rectangle = function(width, height) {
// 생성자
this.width = width;
this.height = height;
}
Rectangle.prototype.getArea = function() {
// (프로토타입) 메서드
return this.width * this.height;
}
Rectangle.isRectangle = function(instance) {
// 스태틱 메서드
return instance instanceof Rectangle && instance.width > 0 && instance.height > 0
}
var rect1 = new Rectangle(3,4)
console.log(rect1.getArea());
/**
* 답: 12
* 해설: [프로타입 메서드] rect1.__proto__.getArea
*/
console.log(rect1.isRectangle(rect1));
/**
* 답: Error
* 해설: rect1 인스턴스에 메서드 없음, rec1.__proto__ 에 없음, rect1.__proto__.__proto__ (=Object.prototype) 없음
*/
console.log(rect1.Rectangle.isRectangle(rect1));
/**
* 답: true
* 해설: [static 메서드]생성자 함수를 this로 해야만 호출가능
*/
// 7-2 Grade 생성자 함수 및 인스턴스
var Grade = function() {
var args = Array.prototype.slice.call(arguments);
for (var i = 0; i < args.length; i++) {
this[i] = args[i];
}
this.length = args.length;
}
Grade.prototype = [];
var g = new Grade(100, 80)
console.log(g)
/**
* 답: Object { 0: 100, 1: 80, length: 2 }
* 해설:
* - 완벽한 superclass, subclass 구조가 아님
* - length 프로퍼티가 configurable, Grade.prototype에 빈배열을 참조시켰음
*/
// 7-3 length 프로퍼티를 삭제하는 경우
var Grade = function() {
var args = Array.prototype.slice.call(arguments);
for (var i = 0; i < args.length; i++) {
this[i] = args[i];
}
this.length = args.length;
}
Grade.prototype = [];
var g = new Grade(100, 80)
g.push(90);
console.log(g)
/**
* 답: Object { 0: 100, 1: 80, 2: 90, length: 3 }
* 해설: 의도된 출력
*/
delete g.length
g.push(70)
console.log(g)
/**
* 답: Object { 0: 70, 1: 80, 2: 90, length: 1 }
* 해설:
* - 의도 되지 않은 출력
* - g.length가 없으니 프로토타입 체이닝을 타고 g.__proto__.length를 읽어온 것
* - 빈 배열의 length가 0, 여기에 length는 1만큼 증가
*/