본문 바로가기

Programming

[JavaScript] Prototype Chain - ES5와 ES6로 상속 구현하기

Reference
- 코드 스테이츠 이머시브 코스 - Inheritance Patterns 강의 
- 위키피디아 - 프로토타입
- MDN - 상속과 프로토타입
- http://insanehong.kr/post/javascript-prototype/
- https://medium.com/@chamikakasun/javascript-prototype-and-prototype-chain-explained-fdc2ec17dd04
 

Javascript 기초 - Object prototype 이해하기 | Insanehong's Incorrect Note

소개 이번 글에서 다룰 내용은 자바스크립트의 프로토타입 상속(prototypal inheritance) 이라는 확장과 객체의 재사용을 가능하게 해주며 class 기반으로 인스턴스를 생성하지 않는 자바스크립트에서

insanehong.kr

 

 

JavaScript Prototype and Prototype Chain explained.

JavaScript Prototype and Prototype Chain explained.

medium.com

 

프로토타입?

객체지향 프로그래밍에서 언급했듯이 자바스크립트는 프로토타입 기반 언어이다. 프로토타입 기반 프로그래밍 객체지향 프로그래밍의 한 형태의 갈래로 클래스가 없고, 클래스 기반 언어에서 상속을 사용하는 것과는 다르게, 객체를 원형(프로토타입)으로 하여 복제의 과정을 통하여 객체의 동작 방식을 다시 사용할 수 있다. 프로토타입기반 프로그래밍은 클래스리스(class-less), 프로토타입 지향(prototype-oriented) 혹은 인스턴스 기반(instance-based) 프로그래밍이라고도 한다.

 

__proto__?

__proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킨다. 상속관계를 통하여 상위 프로토타입으로 연속해서 이어지는 관계를 프로토타입 체인이라고 하는데 이 연결을 __proto__를 이용해 따라 올라갈 수 있다.  

Object는 자바스크립트에서 선언된 모든 것들의 조상님이다.

__proto__를 타고 가다보면 최종적으로 Object 객체의 prototype Object에 다다르는 것을 알수 있다. 그렇기 때문에 자바스크립트의 모든 객체는 Object 객체에서부터 파생되어 나온 자식들이라 한다. 이 Object에 바로 .toString() 메소드가 있다.

 

 

Dog라는 클래스를 상속하는 Maltese 클래스를 두가지 방법으로 구현하기

 

울집 예뿌니

 

ES5 Pseudoclassical로 상속 구현하기

 

Dog는 age, sound를 인자로 받고 birthDay와 say라는 메소드가 있다. 

birthDay을 실행하면 age가 추가되고 say를 실행하면 sound가 출력된다.

 

var Dog = function(age, sound) {
    this.age = age;
    this.sound = sound;
};

Dog.prototype.birthDay = function() {
	this.age += 1;
};
Dog.prototype.say = function() {
	console.log(this.sound);
};

 

Maltese는 Dog를 상속받지만 추가로 name이라는 인자를 받으며,

color라는 생성자와 play라는 메소드가 추가되었다.

play를 실행하면 `우리 ${this.name}이는 예쁜 ${this.color} 강아지!`를 출력한다.

 

var Maltese = function(age, sound, name){
    Dog.apply(this, arguments);
    this.name = name;
    this.color = '흰색'
}

Maltese.prototype = Object.create(Dog.prototype);
Maltese.prototype.constructor = Maltese;

Maltese.prototype.play = function(){
    console.log(`우리 ${this.name}이는 예쁜 ${this.color} 강아지!`)
    }

Object.create를 사용하는 이유

Maltese.prototype = Dog.prototype으로 할당했을때, Maltese(인스턴스)만의 메소드 play를 만들때,

Maltese.prototype.play === Dog.prototype.play가 되어 Dog(클래스)의 메소드가 되어버린다.

그렇기에 Object.create을 이용하여 Dog.prototype의 복제본을 만들어 Maltese.prototype 할당해야 다형성을 활용할 수 있다. 

 

Constructor를 다시 지정해줘야 되는 이유

Object.create를 이용하여 클래스의 프로토타입 사본을 만들게 되면 여전히 생성자는 class로 남아있기 때문에 생성자를 인스턴스로 다시 지정해줘야 정확한 상속이 된다. 자바스크립트가 완전한 객체지향언어가 아닌 프로토타입기반 언어이기 pseudoclassical하게 상속을 구현하려면 어쩔 수 없는 부분이다...

 

 

ES6로 상속 구현하기

class Dog {
    constructor(age, sound){
        this.age = age;
        this.sound = sound;
    }
    birthDay(){
        this.age++;
    }
    say(){
        console.log(this.sound);
    }
}

 

ES6 문법인 super를 사용해서 Dog 생성자의 this를 가져올 수 있다. 

 

class Maltese extends Dog{
    constructor(age, sound, name){
        super(age, sound);
        this.name = name;
        this.color = '흰색'
    }
    play(){
        console.log(`우리 ${this.name}이는 예쁜 ${this.color} 강아지!`)
    }
}