본문 바로가기
Front-End/JavaScript

psuedoclassical VS class[ES6] 상속 방법

by 연제원 2021. 1. 16.

자바스크립트는 프로토타입 기반 객체지향 언어언어다.

그렇기 때문에 class라는 개념이 없어서 prototype을 기반으로 class를 흉내냈다!

(ES6에서 class 문법이 추가되었지만 클래스가 아닌 프로토타입을 기반으로 한 문법)

 

지금까지 class를 통해 객체(인스턴스)를 만드는(흉내) 프로토타입에 대해 이해를 했다면, 오늘은 객체지향의 특징 중 하나인 클래스에서 클래스로 행해지는 '상속'에 대해 공부해보려고 한다.

 


✅ psuedoclassical (prototype)

ES6에서 class 문법이 추가되기 전에 class를 흉내내기 위한 방법 중 하나이다.

다음 예시는 Human - Student 상속을 구현하는 과정이다.

방법 뿐만아니라, 추가적인 것들도 알아보자.

 

우선 복습을 해보자면, prototype을 통해 class기능을 구현하고 생성자 함수와 new연산자를 통해 객체(인스턴스)를 생성한다.

// class 기능 구현
var Human = function (name) {
  this.name = name; // 속성(프로퍼티) 추가
  this.age = 0;     // 속성(프로퍼티) 추가
} 
Human.prototype.sleep = function() {       // 메서드 추가
  console.log(`${this.name} is sleeping`);
}

// 객체(인스턴스) 생성
var jewon = new Human ('jewon');

(나 혼자 공부 - 차이점)

생성자 함수 내에서 this를 사용하지 않고, 원본 객체에 메소드나 프로퍼티를 정의하게 되면 객체들에게는 해당 프로퍼티나 메소드가 없고, 원본 객체의 프로퍼티나 메소드를 참조한다.

따라서 각 객체마다 고유한 프로퍼티를 부여하고 싶다면 원본 객체에 정의하는 것이 아니라, 생성자 함수 내에서 this를 사용하여 정의해야 한다.

 

 

상속

코드가 길어서 공부하는 입장에서 보기 힘들겠지만, 중요하다고 생각되는 것들을 나열했다.

// 부모 클래스 역할
var Human = function (name) {
  this.name = name;
  this.age = 0;
}
Human.prototype.sleep = function() {
  console.log(`${this.name} is sleeping`);
}
Human.prototype.eat = function() {
  console.log(`${this.name} is eating`)
}

// 자식 클래스 역할(상속 받음)
var Student = function (name, age, grade) { 
  Human.call(this, name); // 중요 1
  this.age = age; // 프로퍼티 변경 가능
  this.grade = grade; // 프로퍼티 추가 가능
}

Student.prototype = Object.create(Human.prototype); // 중요 2
Student.prototype.constructor = Student; // 중요 3

Student.prototype.study = function() { // 메서드 추가 가능
  console.log(`${this.name} is studying`)
}
Student.prototype.sleep = function() { // 메서드 변경 가능
  console.log(`${this.name} is sleeping!!!!`);
}
// Student.prototype.eat = function() {  따로 적지 않아도 됨. 참조해서 사용가능하기 때문에
//   console.log(`${this.name} is eating`)
// }

let jewon = new Human('jewon');
let studentJewon = new Student('jewon', 20, 1);

위 코드를 보면 중요 표시가 있는데 프로토타입 기반 상속에 있어서 꼭 중요한 과정 3가지다.

 

중요 1. this 타겟 변경

Funtion.prototype.call 메소드나 Funtion.prototype.apply 메소드는 호출된 함수의 실행 컨텍스트를 첫 번째 인자로 받은 녀석으로 변경한다. 즉, this의 타겟을 변경하는 것이다.

Human,call(this, name)의 의미는 부모 생성자 함수의 생성자를 호출하되, 실행 컨텍스트를 자식 생성자 함수로 변경한다는 뜻이다.

중요 2. 부모 자식 관계를 만듬

Object.create 메소드를 사용해 Human.prototype 객체를 원본 객체로 하는 새로운 객체를 생성하고, 이 객체를 Student의 프로토타입 객체로 할당해준다. 쉽게 말해 부모 자식 관계를 만들어 주는 것이다.

 

중요 3. 자식 생성자 함수를 통해 객체를 생성하게 해주는 능력 부여

부모 생성자 함수의 프로토타입 객체를 그대로 복제했기 때문에, 새롭게 생성한 자식 생성자 함수의 프로토타입 객체의 constructor 프로퍼티는 여전히 부모 생성자 함수인 Human을 참조하고 있다.

하지만 자식 생성자인 Student를 통해 생성된 객체가 Human을 사용하여 생성되면 안되므로, constructor 프로퍼티를 Student로 변경해주는 것이다.

 

 


✅ class (ES6)

ES6 문법이 등장하고 나서, 위의 과정들을 손쉽게 진행할 수 있는 방법이 생겨났다.

바로 class이다. 어떻게 쉬워졌는지 위의 코드와 비교해보자.

class Human { // class 생성
  constructor (name) {
    this.name = name;
    this.age = 0;
  }
  sleep() {
    console.log(`${this.name} is sleeping`)
  }
  eat() {
    console.log(`${this.name} is eating`)
  }
  walk() {
    console.log(`${this.name} cannot walk`)
  }
 }
 
 class Student extends Human { // class 자식 extends 부모
   constructor(name, age, grade) {
     super(name); // 프로퍼티 상속 시 꼭 필요
     this.age = age;
     this.grade = grade;
   }

// super.eat(); 단순히 부모 메소드 가져올 경우 (생략 가능)
// 단순히 부모 메소드를 변경하고 싶을 때 (부모 메서드 기능 X)
   sleep() {
     console.log(`${this.name} is sleeping!!!`)
   }
// 자식 메서드 추가
   study() {
     console.log(`${this.name} is studying`)
   }
// 부모 메서드도 쓰고 싶을 때,
   walk() {
    super.walk();
    console.log(`but ${this.name} can walk now`)
   }
 }

중요한 키워드는 class, constructor, super 이다.

 

참고로 일반 함수 선언과 클래스 선언의 중요한 차이점은, 함수 선언의 경우 호이스팅이 일어나지만, 클래스 선언은 그렇지 않다. 따라서 클래스를 사용하기 위해서는 클래스를 먼저 선언해야한다.

 

'Front-End > JavaScript' 카테고리의 다른 글

[JS] 자바스크립트 Event Loop  (0) 2021.06.07
자바스크립트 비동기 처리 방식  (0) 2021.02.02
프로토타입(Prototype) 이해하기(2)  (0) 2021.01.15
프로토타입(Prototype) 이해하기(1)  (0) 2021.01.15
this  (0) 2021.01.12

댓글