Open KimHyeSeon opened 4 years ago
7-3 클래스 상속 7-3-1 기본 구현 프로토타입 체인을 활용해 클래스 상속 구현, 클래스와 비슷한 형태로 구현 클래스에 있는 값이 인스턴스의 동작에 영향을 줘서는 안됨 구체적인 데이터를 지니지 않고 오직 인스턴스가 사용할 메서드만을 지니는 틀로 작용하게끔!
var Rectangle = function (width, height) {
this.width = width;
this.height = height;
};
Rectangle.prototype.getArea = function () {
return this.width * this.height;
};
var rect = new Rectangle(3, 4);
console.log(rect.getArea()); //12
var Square = function (width) {
this.width = width;
};
Square.prototype.getArea = function () {
return this.width * this.width;
};
var sq = new Square(5);
console.log(sq.getArea()); //25
▼ Square에서 getArea를 Rectangle와 동일하게 적용하도록 변경
var Square = function (width) {
this.width = width;
this.height = width;
};
//getArea 메서드는 동일한 작용을 하므로 상위 클래스(Rectangle)에서만 정의
//하위 클래스(Square)에선 해당 메서드 상속하면서 height대신 width 넣어주면 됨
Square.prototype.getArea = function () {
return this.width * this.height;
};
▼
var Square = function (width) {
Rectangle.call(this, width, width);
};
Square.prototype = new Rectangle();
7-3-2 클래스가 구체적인 데이터를 지니지 않게 하는 방법
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; //빈 함수가 Rectangle.prototype 참조
Square.prototype = new Bridge(); //Square에 Bridge 할당하면 Bridge자리에 Rectangle인 셈
object.freeze(Square.prototype);
//(...생략)
Square.prototype = object.create(Rectangle.prototype); //Square: subClass, Rectangle: superClass
Object.freeze(Square.prototype);
//(...생략)
7-3-3 constructor 복구하기
// 인스턴스 생성 후 프로퍼티 제거
var extendClass1 = function (SuperClass, SubClass, subMethods) {
SubClass.prototype = new SuperClass();
for (var prop in SubClass.prototype) P{
if (SubClass.prototype.hasOwnProperty(prop)) {
delete SubClass.prototype[prop];
}
}
SubClass.prototype.constructor = SubClass;
if (subMethods) {
for(var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
retrun SubClass;
};
//빈 함수 활용
var extendClass2 = (function () {
var Bridge = function () P{;
return function (SuperClass, SubClass, subMethods) {
Bridge.prototype = SuperClass.prototype;
SubClass.prototype = new Bridge();
SubClass.prototype.constructor = SubClass;
Bridge.prototype.constructor = SuperClass; //SubClass.prototype이 SuperClass 바라보도록!
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
return SubClass;
};
})
// Object.create 활용
var extendClass3 = function (SuperClass, SubClass, subMethods){
SubClass.prototype = Object.create(SuperClass.prototype);
SubClass.prototype.constructor = SubClass;
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method[;
}
}
Object.freeze(SubClass.prototype);
return SubClass;
};
7-3-4 상위 클래스에서의 접근 수단 제공 어렵게 느껴진다면 건너뛰어도 무방^^!(저자가 구현한 것) 하위 클래스에서 상위 클래스의 프로토타입 메서드에 접근하기 위한 별도의 수단인 super 흉내내기
// 생략
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);
}
};
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 = ['a','b','c','d'];
var g = new Grade(100, 80);
g.push(90);
console.log(g) // grade (0:100, 1:80, 2:90, length: 3);
delete g.length;
g.push(70);
console.log(g); // Grade {0:100, 1:80, 2:90, __ 4:70, length: 5}
클래스 값이 인스턴스의 영향을 줘서는 안된다.
인스턴스 생성 후 프로퍼티 제거
var extendClass1 = function(SuperClass, SubClass, subMethods) {
SubClass.prototype = new SuperClass();
for (var prop in SubClass.prototype) {
if (SubClass.prototype.hasOwnproperty(prop)) {
delete SubClass.prototype[prop];
}
}
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
return SubClass;
}
var Square = extendClass1(Rectangle, function (width) {
Rectangle.call(this,width, width);
})
2.SubClass의 prototype에 직접ㅂ SuperClass의 인스턴스를 할당하는 대신 아무런 프로퍼티를 생성하지 않는 빈 생성자 함수를 하나 더 만들어서 그 prototype을 바라보게끔 한 다음, SubClass의 prototype에는 Bridge의 인스턴스를 할당 하는 것
클래스 상송 및 추상화 방법 - 빈함수를 활용
var extendClass2 = (function (){
var Bridge = function() {};
return function (SuperClass, SubClass, subMethods) {
Bridge.prototype = SubClass.prototype;
SubClass.prototype = new Bridge();
if (subMethods) {
for(var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SuperClass.prototype);
return SubClass;
}
})();
3.Object.cteate 를 이용한 방법 (가장 간단하면서도 안전하다)
Square.prototype = Object.create(Rectangle.prototype);
Object.freeze(Square.prototype)
위 세가지 방법으로 상속에는 성공했지만 constructor은 여전히 SuperClass를 가리키는 상태이다. 위 코드들의 SubClass.prototype.constructor가 원래의 sub class 를 바라보도록 해주면 된다.
var extendClass1 = function(SuperClass, SubClass, subMethods) {
SubClass.prototype = new SuperClass();
for (var prop in SubClass.prototype) {
if (SubClass.prototype.hasOwnproperty(prop)) {
delete SubClass.prototype[prop];
}
}
SubClass.prototype.constructor = SubClass; // 추가
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
return SubClass;
}
2.
var extendClass2 = (function (){
var Bridge = function() {};
return function (SuperClass, SubClass, subMethods) {
Bridge.prototype = SubClass.prototype;
SubClass.prototype = new Bridge();
SubClass.prototype.constructor = SubClass;//추가
Bridge.prototype.constructor = SuperClass; //추가
if (subMethods) {
for(var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SuperClass.prototype);
return SubClass;
}
})();
3.
var extendClass3 = function(SuperClass, SubClass, subMethods) {
SubClass.prototype = Object.create(Rectangle.prototype);
SubClass.prototype.constructor =SubClass; //추가
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 rect = new Rectangle(3, 4);
console.log(rect.getArea()); // 12
var Square = function (width) {
this.width = width;
};
Square.prototype.getArea = function () {
return this.width * this.width;
};
var sq = new Square(5);
console.log(sq.getArea()); // 25
var Square = function (width) {
this.width = width;
this.height = width;
};
Square.prototype.getArea = function () { return this.width * this.height; };
<br>
- getArea 메서드는 동일한 작용을 하므로 상위 클래스(Rectangle)에서만 정의
- 하위 클래스(Square)에선 해당 메서드 상속하면서 height대신 width 넣어주면 됨
```javascript
var Square = function (width) {
Rectangle.call(this, width, width);
};
Square.prototype = new Rectangle();
var extendClass1 = function(SuperClass, SubClass, subMethods) {
SubClass.prototype = new SuperClass();
for (var prop in SubClass.prototype) {
if (SubClass.prototype.hasOwnproperty(prop)) {
delete SubClass.prototype[prop];
}
}
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
return SubClass;
}
var Square = extendClass1(Rectangle, function (width) {
Rectangle.call(this,width, width);
})
var extendClass2 = (function (){
var Bridge = function() {};
return function (SuperClass, SubClass, subMethods) {
Bridge.prototype = SubClass.prototype;
SubClass.prototype = new Bridge();
if (subMethods) {
for(var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SuperClass.prototype);
return SubClass;
}
})();
Square.prototype = Object.create(Rectangle.prototype);
Object.freeze(Square.prototype)
var extendClass1 = function (SuperClass, SubClass, subMethods) {
SubClass.prototype = new SuperClass();
for (var prop in SubClass.prototype) P{
if (SubClass.prototype.hasOwnProperty(prop)) {
delete SubClass.prototype[prop];
}
}
SubClass.prototype.constructor = SubClass;
if (subMethods) {
for(var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
retrun SubClass;
};
var extendClass2 = (function () {
var Bridge = function () P{;
return function (SuperClass, SubClass, subMethods) {
Bridge.prototype = SuperClass.prototype;
SubClass.prototype = new Bridge();
SubClass.prototype.constructor = SubClass;
Bridge.prototype.constructor = SuperClass; //SubClass.prototype이 SuperClass 바라보도록!
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method];
}
}
Object.freeze(SubClass.prototype);
return SubClass;
};
})
var extendClass3 = function (SuperClass, SubClass, subMethods){
SubClass.prototype = Object.create(SuperClass.prototype);
SubClass.prototype.constructor = SubClass;
if (subMethods) {
for (var method in subMethods) {
SubClass.prototype[method] = subMethods[method[;
}
}
Object.freeze(SubClass.prototype);
return SubClass;
};
study 완료 후 체크 부탁드립니다.