클래스란?
클래스란 특정 집단을 묶기 위해 추상화 한 개념, 이 안에 속하는 것들을 인스턴스라고 함
프로그래밍에서 인스턴스에서 클래스들은 직계존속. 인스턴스를 생성할 때 호출할 수 있는 클래스는 오직 하나이기 때문.
자바스크립트의 클래스
인스턴스에 상속되는지에 따라
- 스태틱 멤버
- 인스턴스 멤버
로 구분됨
자바스크립트에서는 인스턴스에서도 직접 메서드를 정의할 수 있음. 그래서 인스턴스 메소드보단
프로토타입 메서드라고 부름
// 생성자
var Rectangle = function (width, height) {
this.width = width;
this.height = height;
};
// prototype method
Rectangle.prototype.getArea = function () {
return this.width * this.height;
};
// static method
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
console.log(rect1.isRectangle(rect1)); // error
console.log(Rectangle.isRectangle(rect1)); // true
rect1 에 3,4를 할당. 프로토타입 객체에 할당한 메서드는 인스턴스가 마치 자신의 것 마냥 호출할 수 있으니까 그 다음 rect1.getAreat는 프로토타입 객체에 할당된 getAreat를 호출한 셈이니 결과값이 제대로 반환됨. 이것은 인스턴스에서 직접 프로토타입 메서드를 호출한 경우임
그 다음엔 rect1 인스턴스에서 isRectangle이라는 메서드에 접근하는 경우인데. rect1에 해당 메서드(isRectangle)가 있는지 검색했는데 없고. rect1의 프로토타입에도 없으므로 결국 에러가 남.
이렇게 인스턴스에서 직접 접근할 수 없는 메서드를 스태틱 메서드라고 함.(둘다 메서드니까)
이 경우 바로 아래처럼 rect1의 부모 생성한테 접근해야 원기능 사용이 가능함.
클래스 상속
ES6에서는 다른 방법이 존재한다니까 읽고 넘기면 됨
프로토 타입 체인을 활용
// 프로토타입 체이닝
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 = []; // Grade의 기본 타입을 array로 변경하는 것.
var g = new Grade(100,80);
프로토 타입 체이닝을 이용해 클래스 상속을 구현 함
Array.prototype.slice.call(arguments)란 이 코드가 존재하는 함수의 매개변수로 넘어온 값들을 유사배열객체로 변환하겠다는 뜻
그래서 문제점은?
g.push(80);
console.log(g); //Array { '0': 100, '1': 80, '2': 80, length: 3 }
delete g.length;
g.push(90);
console.log(g); //Array { '0': 90, '1': 80, '2': 80, length: 1 }
내장객체인 배열 인스턴스의 length는 configurable(삭제 가능)속성이 false라서 삭제가 불가능.
그러나 Grade클래스의 인스턴스는 배열 메서드를 상속하나 일반 객체의 성질을 지니므로 삭제가 됨.
근데 왜 100이 없어진걸까?
Grade.prototype이 빈 배열을 가리키고 있기 때문. 빈배열의 length가 0이므로 여기에 값을 할당하고 length는 1만큼 증가시키라는 명령.
그런데 length가 Grade.prototype에 포함하는 경우라면?
Grade.prototype에 요소를 포함하는 배열을 매칭시켰다면?
Grade.prototype = ['a','b','c','d']; // Grade의 기본 타입을 array로 변경하는 것.
var g = new Grade(100,80);
g.push(90);
console.log(g); //Array { '0': 100, '1': 80, '2': 90, length: 3 }
delete g.length;
console.log(g); //Array { '0': 100, '1': 80, '2': 90 }
g.push(70);
console.log(g); //Array { '0': 100, '1': 80, '2': 90, '4': 70, length: 5 }
이거는 g.push(70)에서 length가 없으니까 prototype에서 length(4)를 찾아서 가져오는 것
그 뒤에것들을 공부를 못했음
ES6에서의 클래스 상속
여기서는 ES5 체계에서의 생성자 함수 및 프로토타입과 ES6의 클래스 문법을 비교.
ES5
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()); //ES5 staticMethod
console.log(es5Instance.method()); //es5 method
ES6
var ES6 = class{
constructor (name){
this.name = name;
}
static staticMethod(){
return this.name + ' staticMethod';
}
method = function(){
return this.name + ' method';
}
}
var es6Instance = new ES6('es6');
console.log(ES6.staticMethod()); //ES6 staticMethod
console.log(es6Instance.method()); //es6 method
class라는 명령어 뒤에 바로 {} 가 등장 , 중괄호 묶음 내부가 클래스 본문 영역
constructor 이름 뒤에 ()가 등장, 클래스 본문에서는 function 키워드를 생략하더라도 모두 메서드로 인식. 이 부분이 생성자 함수와 동일한 역할 수행.
static 메소드(es6 객체만 쓸 수 있는것) 따로 선언
그리고 method가 등장했는데 이는 자동으로 prototype객체 내부에 할당되는 메서드. 인스턴스가 프로토타입 체이닝을 통해 호출 가능한 메서드.
요약
ES5의 생성자함수 => ES6의 class내에서 constructor
ES5의 메서드 => ES6의 static 메서드
ES5의 prototype.메서드 => ES6의 프로토타입 메서드
클래스 상속(ES6)
ES5에는 존재X, ES6에서만 존재.
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());
}
};
Square를 Rectangle 클래스를 상속받는 SubClass로 만들기 위해 class 명령어 뒤에 extends라고 추가.
let square = new Square(10);
square.getArea(); //size is: 100