상속이란 반복적인 코드를 작성하지 않고 코드를 재사용하는 방법을 의미한다. 따라서 코도를 재 사용함으로써 개발기간 단축과 편리한 코드작성을 할수있다.
클래스 기반언어에서 클래스는 객체의 형식이 정의되어 있고, 클래스를 화용하여 객체(Instance)
를 생성한다.
하지만 프로토 타입 기반 언어에서는 클래스라는 개념이 없고, 객체에서 객체를 바로 상속할수있다.
프로토타입이란?
자바스크립트에서 기본 데이터 타입을 제외한 모든것이 객체이다. 객체가 만들어지기 위해서는 자신을 만드는데 사용된 원형인 프로토타입 객체를 이용하여 객체를 만든다. 이떄 만들어진 객체안에 _proto_
(비표준) 속성이 자신을 만들어낸 원형을 의미하는 프로토아입 객체를 참조하는 숨겨진링크가 있다. 이러한 숨겨진링크를 프로토타입이라고 정의한다.
function Person(){}
let jin = new Person();
자바스크립트에서는 크게 세가지의 상속방식을 갖는다.
의사 클래스 방식은 가짜 클래스 방식이라고도 한다. 그 이유는 자바스크립트에서는 객체를 표현하기 위하여 함수를 사용하고있다. 자바스크립트는 클래스가 없기 때에 이를 흉내내기위 위해 만들어진 패턴이기 때문이다.
생성자를 만들게 되면, 생성자객체
와 생성자.prototype객체
가 생성되고 생성자.prototype
객체는 원형을 담고 있기 때문에, 상속하고자 하는 부모생성자의 prototype
으로 변경시키는것이 핵심이다.
예시
let Me = function(){
this.name = 'Jin';
this.surname = 'Park';
}
Me.prototype.get_name = function (){
return this.anme;
}
Me.prototype.get_surname = function(){
return this.surname
}
let You = function(){
this.name = 'Strawberry';
this.surname = 'Pocky'
}
위의 예시를 보면 아직까지는 독립적인 함수객체에 불과하다.You 생성자
는 이미 You.prototype
이 생성되어 있기 때문에 이를 Me의 prototype
으로 변경하여 get_name과 get_surname을 사용하도록 해보자.
// You 생성자의 프로토타입을 Me 생성자의 프로토 타입을 가진 객체로 변경
You.prototype = New Me();
let you = new You();
you.get_name();// Strawberry
you.get_surname() // Pocky
You.prototype = New Me();
이 핵심이다. new 연산자를 반드시 사용해야하며, private 속성은 사용할수 없다는 단점이있다.
유사 클래스방식과는 다르게, 객체에서 바로 객체로 상속할수있는 방식이다. 새로운 객체를 생성 후 프로토타입속성에 매개변수로 받은 객체를 할당한다.
if(typeof Object.create != 'function'){
Object.create = function(obj){
function F(){};
F.prototype = obj;
return new F();
}
}
위의 예제처럼 사용법은 Object.create() 메소드를 호출하는것이다. 새로운 함수객체를 생성 후 프로토타입에 매개변수로 받아온 객체를 할당하는 로직이다.
let me = {
name : 'Jin',
surname : 'Park',
get_name : function(){
return name;
},
get_surname : function(){
return surname;
}
}
let you = Object.create(me);
you.name; // Park
you.get_name(); // Park;
객체를 바로 상속할 수있는 이 방법은 자바스크립트의 특성을 잘 반영한 방법이다. 그러나, 모든 속성이 Public하다는 단점이 있다.
함수객체에서 함수를 상속하는 방법이다. 부모 함수객체에서 새로운 객체를 생성하고 상속하고자 하는 속성을 할당하고 반환한다. 자식 함수에서 부모함수를 호출하여 상속받을수있다.
let first = function (spec) {
// 상속하기위해 속성을 담는 객체
let that = {};
// 상송하려는 메소드
that.get_name = function () {
return spec.name;
};
// 상속하려는 메소드2
that.get_ability = function () {
return spec.ability;
};
// 코드 마지막에 생성했던 객체를 반환한다.
return that;
};
let second = first({'name':'jin', 'ability':'thinking'})
console.log(second.get_name()); // jin
생성자가 아니기 때문에 이름은 소문자로 지정한다. 여기서 보면 알겠지만, 객체를 매개변수로 활용하고 있다는점이다. 이로인한 장점으로는, 여러값을 주고 받을 떄 수선에 신경쓸 필요가 없다는점이다.
let second = first({ name: "jin", ability: "thinking" });
console.log(second.get_name()); // jin
//자식함수에 부모함수 상속
let third = function (spec) {
spec.ability = spec.ability || "game";
let that = first(spec);
// first 부터 ability에 대한 호출 값을 가져와서 저장한다
super_get_ability = that.get_ability();
//get_ability 함수를 재정의 한다
that.get_ability = function () {
return "this is new ability " + super_get_ability;
};
return that;
};
let fourth = third({ name: "pocky" });
console.log(fourth.get_name()); // pocky
console.log(fourth.get_ability()); // this is new ability game
자식 함수에서 부모를 상속하려면 그저 부모를 호출하기만 하면된다. 부모에서 전달한 메소드를 사용하고 override할수있다.
위에서 suer_get_ability 값은 부모 속성에서 반환하는겂을 저장하는 변수에 불과하다.
부모의 메소드를 호출하는 super()메소드 사용법
Object.prototype.super = function (name) {
// 호출한 객체를 that에 할당한다
let that = this;
// 객체에서 이름으로 메소드를 찾아온다
let method = that[name];
// 찾아온 메소드를 실행할 때, 호출객체와 매개변수를 활용한다.
return function () {
return method.apply(that, arguments);
};
};
let fifth = function(spec){
spec.ability = spec.ability || 'game'
let that = first(spec);
// 부모객체의 메소드를 찾아서 가져온다
let super_get_ability = that.super('get_ability');
//get_ability 함수를 재정의 한다
that.get_ability = function(){
return 'this is new ability ' + super_get_ability();
}
return that
}
let sixth = fifth({name:'coffee'});
sixth.get_ability(); // this is new ability game
자식객체에서 override 후 that.super()으로 호출하면 재 정의된 값을 반환하기 때문에 override하기 전에 미리 변수에 할당하도록 한다.
출처 : https://www.nextree.co.kr/p7323/
출처 :https://chrisjune-13837.medium.com/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-7c275edaa9e6
출처 : https://velog.io/@y1andyu/JavaScript-Decorator
https://velog.io/@y1andyu/JavaScript-Decorator