Js Class 와 prototype 의 차이

Sooka
6 min readFeb 3, 2020

스타일의 문제일까?

Class 상속

클래스로부터 인스턴스를 상속 받는다(ex.설계도). new 키워드를 통해 인스턴스를 생성할 수 있고 하위 클래스를 만들 수 있다. es6의 class 키워드를 사용 혹은 사용하지 않고 class 상속을 만들 수 있다.

Prototype 상속

다른 객체로 부터 직접 인스턴스가 상속된다. Factory function 이나 Object.create()을 통해 인스턴스를 상속할 수 있다. 다양하게 구성된 객체로 쉽게 선택적인 상속을 구현할 수 있다.

Class inheritance 와 Prototypal inheritance 는 같은가?

  • Class 상속에서 인스턴스는 설계도(Class)로 하위 클래스 관계를 생성한다. 다시말해, 클래스를 인스턴스를 사용하는 것 처럼 사용할 수 없다. Class의 정의에 인스턴스의 함수를 불러올 수 없다. 인스턴스를 먼저 생성한 후에 해당 함수를 불러올 수 있다.
  • Prototype 상속에서 인스턴스는 다른 인스턴스로부터 상속된다. 위임형 상속을 사용하는 것은 말 그대로 다른 오브젝트와 연결된 오브젝트라고 할 수 있다. 프로토타입 객체는 다른 객체의 기반이 된다. 연결상속을 사용하면 새인스턴스로 속성을 복사함으로써 상속을 구현하는 방법이다.

Class 상속을 이용한 방법은 변경하기 어렵고 기반이 되는 클래스를 수정했을 때 하위 클래스들이 영향을 쉽게 받을 수 있는 계급 계층구조를 만든다.

Class는 설계도이다.

Prototype 상속이 반드시 유사한 계층구조를 생성하지는 않는다. 프로토타입 체인을 최대한 간결하게 만드는 것이 중요하다.

Prototype은 오브젝트 인스턴스이다.

Using class inheritance in JavaScript is like driving your new Tesla Model S to the dealerand trading it in for a rusted out 1983 Ford Pinto. -Eric Elliott

프로토타입 기반의 프로그래밍 언어인 자바스크립트에서 Class 키워드가 추가되었다고 해서 자바스크립트가 Class기반의 언어가 되었다는 것이 아니다. 프로토타입 기반은 클래스 기반의 구시대적 방법보다 강력한 시스템이 될 수 있다. 프로토타입 기반의 코드를 클래스 기반으로 바꾸는 것은 쉽지만, 반대의 경우는 거의 불가능에 가깝다.

Prototype 상속 예제

function Human(age){
this.age = age;
}
Human.prototype.howoldareyou = function(){
console.log(`this man is ${this.age}years old`;
}
function Chulsoo(age){
Human.call(this, age);
}
Chulsoo.prototype = Object.create(Chulsoo.prototype);
Chulsoo.prototype.constructor = Chulsoo;
Chulsoo.prototype.howoldareyou = function(){ Human.prototype.howoldareyou.call(this);
console.log(`this man called Chulsoo)`;
}var chulsoo = new Chulsoo(12);
chulsoo.howoldareyou()
//this man is 12years old
//this man called Chulsoo
  • new Chulsoo ()가 실행될 때, Chulsoo()가 호출된다. 따라서 Chulsoo()를 생성자함수라고 한다.
  • Human.prototype.howoldareyou는 프로토타입에 메서드를 연결한 형태이다. Object.create()를 통해 Human.prototype에 연결된 메소드를 Chulsoo의 _proto_로 상속한다. Chulsoo.prototype의 constructor에 Chulsoo로 Prototype을 재할당했기 때문에 생성자는 Chulsoo가 된다. prototype에 메서드를 작성하지 않으면 각각의 인스턴스에 메소드가 붙게된다.

Class 상속 예제

class Human{
constructor(age){
this.age = age;
}
howoldareyou() {
console.log(`this man is ${this.age}years old`;
}
}class Chulsoo extends Human {
howoldareyou(){
super.howoldareyou();
console.log(`this man called Chulsoo)`;
}
}
const chulsoo = new Chulsoo(12);
chulsoo.howoldareyou()
//this man is 12years old
//this man called Chulsoo

Class 상속에서는 extends 키워드로 상속을 구현하고 하위 클래스를 생성할 수 있다.

  • super : 하위 클래스와 프로토타입 클래스에 같은 이름의 메소드가 있을 경우에 기본적으로 프로토타입 클래스의 메소드는 호출이 되지않고 하위클래스의 메소드가 호출된다. 이 때 super 키워드를 사용해서 프로토타입 클래스의 메소드를 호출할 수 있다.
  • static : 정적메소드로 프로토타입에 연결되지 않는다. 클래스의 인스턴스에서는 호출할 수 없다.

클래스 상속을 이용하면 코드를 간단하게 구현할 수 있다는 장점이 있지만, 가장 큰 문제로 위에서 언급한 무너지기 쉬운 계층구조가 코드가 길어질수록 커지게 된다.

최근에 Class 상속의 고질적인 문제로 Class 상속의 사용을 자제하자는 의견이 많지만 그럼에도 불구하고 super키워드를 이용하여 subclass를 구현하는 등 편리한 부분이 분명히 존재하기 때문에 반드시 공부할 필요가 있을 것 같다.

--

--