본문 바로가기

Frontend Dev/JavaScript

ES6, 자바스크립트의 클래스(class) 기본 문법과 클래스 상속

반응형

객체 지향 프로그래밍과 클래스

객체 지향 프로그래밍은 하나의 모델이 되는 청사진(blueprint)을 만들고,

그 청사진을 바탕으로 한 객체(object)를 만드는 프로그래밍 패턴이다.

 

  → 청사진을 클래스(class)

  → 청사진을 바탕으로 한 객체를 인스턴스 객체(instance object) 라고 부른다.

 

📌 클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메서드를 정의하는 일종의 틀로, 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.

📌 자바스크립트에서 클래스는 함수의 한 종류로 기존 prototype 기반 패턴의 syntactic sugar(기존 문법을 쉽게 읽을 수 있게 만든 문법)이다.

 

💬 클래스는 ES6에서 추가된 문법으로, ES6 이전에는 클래스를 어떤 방식으로 구현했는지 먼저 알아보고, 클래스의 기본 문법과 클래스 상속에 대해 알아보자.

 

👩🏻‍💻 ES5와 ES6의 프로토타입으로 클래스 구현 예시

example 1. 간단 예시 (create Car)

/* ES5: 함수로 클래스를 정의 */
function Car(brand, name, color) { // 생성자 함수
  this.brand = brand;
  this.name = name;
  this.color = color;
}

// 메서드 정의
Car.prototype.refuel = function() { ... }
Car.prototype.drive = function() { ... }
/* ES5: 함수로 클래스를 정의 */
function Car(brand, name, color) { // 생성자 함수
  this.brand = brand;
  this.name = name;
  this.color = color;
}

// 메서드 정의
Car.prototype.refuel = function() { ... }
Car.prototype.drive = function() { ... }

 

example 2. 좀 더 복잡한 예시 + 상속 (make Cocktatil)

/* ES5: 함수로 클래스를 정의  */
function Cocktail(name, base, method) { // 생성자 함수
  this.name = name;
  this.base = base;
  this.method = method;
}

// 메서드 정의
Cocktail.prototype.make = function() { console.log( `${this.method} 하는 중...` ) }
Cocktail.prototype.serve = function() { console.log( `${this.name} 서빙중...` ) }

// 상속
function Highball(name, base, method, softDrink) {
  Cocktail.call(this, name, base, method);
  this.softDrink = softDrink;
}

Highball.prototype = Object.create(Cocktail.prototype);
Highball.prototype.constructor = Highball;

Highball.prototype.putIce = function(num) {
  console.log( `얼음 ${num}개 넣는 중...` );
}

const cosmopolitan = new Cocktail("cosmopolitan", "vodka", "shake");
const whiskyHighball = new Highball("whiskyHighball", "whisky", "build", "soda");

console.log( cosmopolitan ); // Cocktail { name: 'cosmopolitan', base: 'vodka', method: 'shake' }
console.log( cosmopolitan.make() ); // shake 하는 중...
console.log( cosmopolitan.serve() ); // cosmopolitan 서빙중...
console.log( cosmopolitan.putIce() ); // TypeError: cosmopolitan.putIce is not a function

console.log( whiskyHighball ); // Highball { name: 'whiskyHighball', base: 'whisky', method: 'build', softDrink: 'soda' }
console.log( whiskyHighball.make() ); // build 하는 중...
console.log( whiskyHighball.serve() ); // whiskyHighball 서빙중...
console.log( whiskyHighball.putIce(10) ); // 얼음 10개 넣는 중...
/* ES6: class 키워드로 정의 */
class Cocktail {
  constructor(name, base, method) { // 생성자 함수
    this.name = name;
    this.base = base;
    this.method = method;
  }

  // 메서드 정의
  make() { console.log( `${this.method} 하는 중...` ) }
  serve() { console.log( `${this.name} 서빙중...` ) }
}

// 상속
class Highball extends Cocktail {
  constructor(name, base, method, softDrink) {
    super(name, base, method);
    this.softDrink = softDrink;
  }

  putIce(num) { console.log( `얼음 ${num}개 넣는 중...` ) }
}

const cosmopolitan = new Cocktail("cosmopolitan", "vodka", "shake");
const whiskyHighball = new Highball("whiskyHighball", "whisky", "build", "soda");

console.log( cosmopolitan ); // Cocktail { name: 'cosmopolitan', base: 'vodka', method: 'shake' }
console.log( cosmopolitan.make() ); // shake 하는 중...
console.log( cosmopolitan.serve() ); // cosmopolitan 서빙중...
console.log( cosmopolitan.putIce() ); // TypeError: cosmopolitan.putIce is not a function

console.log( whiskyHighball ); // Highball { name: 'whiskyHighball', base: 'whisky', method: 'build', softDrink: 'soda' }
console.log( whiskyHighball.make() ); // build 하는 중...
console.log( whiskyHighball.serve() ); // whiskyHighball 서빙중...
console.log( whiskyHighball.putIce(10) ); // 얼음 10개 넣는 중...

 


 

👾 클래스(class)란?

 ⬇︎ 클래스 기본 문법

// 클래스 생성
class MyClass {
  constructor() {...}
  method1() {...}
  method2() {...}
  ...
}

// 클래스를 통한 인스턴스 객체 생성
const instance1 = new MyClass();

 • 선언식으로 정의한 클래스의 이름은 constructor와 동일하고, constructornew 연산자 없이 호출할 수 없다.

 • 각각의 인스턴스는 클래스의 고유한 속성과 메서드를 가진다.

 • 클래스 이름은 명사들의 조합으로 이루어지며 첫 글자는 대문자로 지정하는 것이 관례이다. (PascalCase)

 

✔️ 생성자 함수 constructor

 constructor는 인스턴스가 초기화될 때 실행하는 생성자 함수로 객체의 기본 상태를 설정해주는 생성자 메서드로 인스턴스가 생성될 때 실행되며 new연산자 에 의해 자동으로 호출된다. (return 값을 만들지 않음)

 

class Student {
  constructor(name, grade, language) {
    this.name = name,
    this.grade = grade,
    this.language = language
  }

  study() {
    console.log("공부를 시작합니다.");
  }
  spaek() {
    console.log("발표를 합니다.")
  }
}

let Elle = new Student("Elle", 2, "English");
Elle.language // English
Elle.study()  // 공부를 시작합니다.

 • constructor는 클래스 내에 한 개만 존재할 수 있으며, constructor의 파라미터에 전달한 값은 클래스 필드에 할당된다.

 • constructor는 생략하면 클래스에 constructor() {} 빈 객체를 생성한다.

   → 인스턴스에 프로퍼티를 추가하려면 인스턴스를 생성한 이후, 프로퍼티를 동적으로 추가해야 한다.

 • constructor는 인스턴스 생성과 동시에 클래스 필드의 생성과 초기화를 실행하기 때문에 클래스 필드를 초기화해야 한다면 constructor를 생략해서는 안된다.

 • constructor는 부모 클래스의 constructor를 호출하기 위해 super 키워드를 사용할 수 있다.

 • constructor 내부에서 선언한 클래스 필드는 클래스가 생성할 인스턴스를 가리키는 this에 바인딩한다

   → 클래스 필드는 클래스가 생성할 인스턴스를 프로퍼티가 되며, 클래스의 인스턴스를 통해 클래스 외부에서 언제나 참조 할 수 있다. (언제나 public)

 

 

✔️ 클래스 필드(class field)

 클래스 필드란 클래스 내부의 캡슐화된 변수를 말한다. 데이터 멤버 또는 멤버 변수라고도 부른다. 클래스 필드는 인스턴스의 프로퍼티 또는 정적 프로퍼티가 될 수 있다. 쉽게 말해, 자바스크립트의 생성자 함수에서 this에 추가한 프로퍼티를 클래스 기반 객체지향 언어에서는 클래스 필드라고 부른다.

 

 • 클래스 필드(class field)를 사용하면 어떤 종류의 프로퍼티도 클래스에 추가할 수 있다.

class Person {
	name = "Jane";
	age = prompt("How old?", "20");

	sayHi() { console.log(`Hi, ${this.name}`) }
}

// new Person().sayHi(); // Hi, Jane

const person = new Person();
person.sayHi() // Hi, Jane

console.log(person.name) // Jane
console.log(person.age) // 20

// name과 age는 Person.prototype이 아닌 개별 객체에 클래스 필드가 설정된다. 
console.log(Person.prototype.name) // undefined 
console.log(Person.prototype.age) // undefined

 → 프로퍼티이름 = “값” 으로 클래스 필드를 만들 수 있다.

 → 클래스 필드에 설정된 값은 class의 prototype이 아닌 개별 객체에 설정된다.

 → 클래스 필드에 복잡한 표현식이나 함수 호출 결과를 사용할 수도 있다.

 

 

👾 클래스 상속

 클래스 상속이란 어떤 클래스의 기능을 다른 클래스에 상속시킨 후 추가적인 기능을 명시하여 원래의 기능을 확장하는 방법이다.

 

✔️ extends 키워드

 class를 정의할 때 클래스 이름 뒤에 extends 키워드를 명시하고 상속받고자 하는 부모 클래스의 이름을 지정한다.

// extends는 부모 클래스(base class)를 상속받는 자식 클래스(sub class)를 정의할 때 사용
class Child extends Parent
/* 기본 기능을 갖는 클래스 */
class sayHello {
  eng() { console.log("Hello Javascript") }
}

/* 기본 기능을 확장하는 클래스 */
// 부모의 기능을 상속받고, 추가로 자신이 구현하는 기능도 사용할 수 있다.

class sayHelloWorld extends sayHello {
  kor() { console.log("안녕하세요. 자바스크립트") }
}

const say = new sayHelloWorld();
say.eng(); //  Hello Javascript
say.kor(); // 안녕하세요. 자바스크립트

 

👩🏻‍💻 example

// 부모 클래스 
class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  run(speed) {
    this.speed = speed;
    console.log(`${this.name} 은/는 속도 ${this.speed}로 달립니다.`);
  }
  stop() {
    this.speed = 0;
    console.log(`${this.name} 이/가 멈췄습니다.`);
  }
}
  
let animal = new Animal("동물");

// 자식 클래스
class Rabbit extends Animal {
  hide() {
    console.log(`${this.name} 이/가 숨었습니다!`);
  }
}
  
let rabbit = new Rabbit("흰 토끼");

rabbit.run(5); // 흰 토끼 은/는 속도 5로 달립니다.
rabbit.hide(); // 흰 토끼 이/가 숨었습니다!

 

👩🏻‍💻 example extends 뒤에 표현식이 올 수도 있다.

function f(phrase) {
  return class {
    sayHi() { alert(phrase) }
  }
}

// class User는 f("Hello")의 반환값을 상속받는다.
class User extends f("Hello") {}

new User().sayHi(); // Hello

 → 이 방법은 조건에 따라 다른 클래스를 상속받고 싶을 때 유용하다. 조건에 따라 다른 클래스를 반환하는 함수를 만들고, 함수 호출 결과를 상속받게 하면 된다.

 

참고로, 리액트에서 컴포넌트를 사용하는 방법이 이와 같다.

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>
  }
}

 

✔️ super 키워드

super 키워드는 부모 클래스를 참조(Reference)할 때 또는 부모 클래스의 constructor를 호출할 때 사용한다.

 

class Human {
  constructor(name, age, location) {
    this.name = name;
    this.age = age;
    this.location = location;
  }

eat(food) { console.log(`${this.name}이 ${food}을(를) 먹습니다.`) }
sleep() { console.log(`${this.name}이 잠을 잡니다.`) }
  live() { 
    console.log(`거주지: ${this.location}`) 
    return `${this.location}`;
  }
}

class Student extends Human {
  constructor(name, age, location, major) {
    super(name, age, location); // ①
    this.major = major;
  }

  study() { console.log(`${this.major} 공부중...`) }
  goToSchool() { console.log(`${super.live()} 에서 학교로 갑니다.`) } // ② 
}

const student = new Student("Amy", 20, "Seoul", "English");

super 메소드는 부모 클래스의 constructor를 호출하면서 인수를 전달한다. 자식 클래스의 constructor에서 super()를 호출하지 않으면 this에 대한 참조 에러가 발생한다.

  → 자식 클래스의 생성자에선 this를 사용하기 전에 반드시 super를 호출해야 한다.

super 키워드는 부모 클래스의 필드 또는 메소드를 참조한다.

 

✔️ 메서드 오버라이드 (override)

 부모 클래스가 가지고 있는 메서드를 자식 클래스가 재정의하여 사용하는 방식으로 자식 클래스가 정의한 메서드에 의해 부모 클래스의 메서드는 가려지게 된다.

 

 


자료출처: poiemaweb, JAVASCRIPT.INFO

✏️ 공부하며 정리한 내용입니다. 잘못된 정보나 더 공유할 내용이 있으면 댓글로 알려주세요!

읽어주셔서 감사합니다 😊

반응형