07 클래스
7-1 클래스와 인스턴스의 개념 이해
- 클래스의 속성을 지니는 실존하는 개체를 일컬어 인스턴스라고 한다.
 
- 한 인스턴스는 하나의 클래스만을 바탕으로 만들어진다.
 
7-2 자바스크립트의 클래스
- 인스턴스에 상속되는지(인스턴스가 참조하는지) 여부에 따라 스태틱 멤버와 인스턴스 멤버로 나뉜다.
 
- 프로토타입 메서드
 

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()); 
console.log(rect1.isRectangle(rect1)); 
console.log(Rectangle.isRectangle(rect1)); 
7-3 클래스 상속
7-3-1 기본 구현
- ES5까지의 자바스크립트에는 클래스가 없다.
 
- 하위 클래스로 삼을 생성자 함수의 prototype에 상위 클래스의 인스턴스를 부여하는 것만으로도 기본적인 메서드 상속은 가능하지만 다양한 문제가 발생.
 
7-3-2 클래스가 구체적인 데이터를 지니지 않게 하는 방법
- 가장 간단한 방법은 일단 만든 후 프로퍼티들을 일일이 지우고 더는 새로운 프로퍼티를 추가할 수 없게 하는 것.
 
- 다른 방법은 SubClass의 prototype에 직접 SuperClass의 인스턴스를 할당하는 대신 아무런 프로퍼티를 생성하지 않는 빈 생성자 함수(Bridge)를 하나 더 만들어서 그 prototype이 SuperClass의 prototype을 바라보게끔 한 다음, SubClass의 prototype에는 Bridge의 인스턴스를 할당하게 하는 것이다.
 
var Rectangle = function (width, height) { 
	this.width = width;
	this.height = height;
};
Rectangle.prototype.getArea = function () { 
	return this.width * this.height;
};
var Square = function (width) {
	Rectangle.call(this, width, width);
};
var Bridge = function () {};
Bridge.prototype = Rectangle.prototype;
Square.prototype = new Bridge();
Object.freeze(Square.prototype);

- Object.create : SubClass의 prototype의 
__proto__가 SuperClass의 prototype을 바라보되 SuperClass의 인스턴스가 되지는 않으므로 위의 두 방법보다 간단하고 안전. 
7-3-3 constructor 복구하기
- SubClass.prototype.constructor가 원래의 SubClass를 바라보도록 해주면 된다.
 
7-3-4 상위 클래스에의 접근 수단 제공
- 하위 클래스의 메서드에서 상위 클래스의 메서드 실행 결과를 바탕으로 추가적인 작업을 수행하고 싶을 때 → ‘super’를 흉내 내본다.
 
var extendClass = function (SuperClass, SubClass, subMethods) {
	SubClass.prototype = Object.create(SuperClass.prototype);
	SubClass.prototype.constructor = SubClass;
	SubClass.prototype.super = function (propName) {
		var self = this;
		if (!propName) return function () {
			SuperClass.apply(self, arguments);
		};
		var prop = SuperClass.prototype[propName];
		if (typeof prop !== 'function') return prop;
		return function () {
			return prop.apply(self, arguments);
		}
	};
	if (subMethods) {
		for (var method in subMethods) {
			SubClass.prototype[method] = subMethods[method];
		}
	}
	Object.freeze(SubClass.prototype);
	return SubClass;
};
var Rectangle = function (width, height) {
	this.width = width;
	this.height = height;
};
Rectangle.prototype.getArea = function () {
	return this.width * this.height;
};
var Square = extendClass(
	Rectangle,
	function (width) {
		this.super()(width, width);
	}, {
		getArea: funtion () {
			console.log('size is :', this.super('getArea')()); 
		}
	}
);
var sq = new Square(10);
sq.getArea(); 
console.log(sq.super('getArea')()); 
7-4 ES6의 클래스 및 클래스 상속
var ES5 = function (name) {
  this.name = name;
};
ES5.staticMethod = function () {
  return this.name + ' staticMethod';
};
ES5.prototype.method = function () {
  return this.name + ' method';
};
var es5Instance = new ES5('es5');
console.log(ES5.staticMethod()); 
console.log(es5Instance.method()); 
var ES6 = class {
  constructor (name) {
    this.name = name;
  }
  static staticMethod () {
    return this.name + ' staticMethod';
  }
  method () {
    return this.name + ' method';
  }
};
var es6Instance = new ES6('es6');
console.log(ES6.staticMethod()); 
console.log(es6Instance.method()); 
var Rectangle = class {
	constructor (width, height) {
    this.width = width;
    this.height = height;
  }
  getArea () {
    return this.width * this.height;
  }
};
var Square = class extends Rectangle {
  constructor (width) {
    super(width, width);
  }
  getArea () {
    console.log('size is: ', super.getArea());
  }
}