[JS] ES6 Class 클래스

daybyday·2021년 2월 9일
0

Javascript

목록 보기
13/15
post-thumbnail

ES5까지 자바스크립트에는 클래스가 없었다. 그래서 프로토타입 체이닝을 통해 클래스와 비슷한 구조를 만들었었다.

그러나 ES6부터 자바스크립트에도 클래스가 추가되었다!

클래스 정의

클래스는 "특별한 함수"이다. 함수와 같이 class 표현class 선언 두 가지 방법으로 정의할 수 있다.

Class 선언

class 키워드와 클래스 이름 사용

class Rectangle{
	constructor(height, width){
    	 this. height = height;
         this.width = width;
    }
}

Class 표현

- 이름이 부여되지 않은 클래스 표현식

let Rectangle = class {
	constructor(height, width){
    	  this.height = height;
          this.width = width;
    }
};

console.log(Rectangle.name); // "Rectangle"

- 이름이 부여된 클래스 표현식

이름을 가진 클래스 표현식의 이름은 클래스 body의 local scope에 한헤 유효하다. 그러나 클래스의 name 속성을 통해 찾을 수 있다.

let Rectangle = class Rectangle2 {
    constructor(height, width){
         this.height = height;
         this.width = width;
    }
};

console.log(typeof Rectangle); // "function"
console.log(typeof Rectangle2); // "undefined"
console.log(Rectangle.name); // "Rectangle2"

이 부분이 잘 이해가 안되는데...

클래스 선언의 경우 let으로 정의한 외부 바인딩은 const로 정의한 내부 바인딩과 동일한 이름(Rectangle)을 가지게 된다.

이름이 부여된 클래스 표현식에서 Rectangle2const 정의 내에만 존재하기 때문에 클래스 내부에서만 사용할 수 있다고 한다. 클래스 밖에서는 Rectangle2 바인딩이 존재하기 않기 때문에 undefined이다.




클래스 body와 메서드 정의

class Rectangle{
	constructor(height, width){
    	 this. height = height;
         this.width = width;
    } // body
}

- Strict mode

클래스의 본문(body)은 strict mode에서 실행된다. 성능 향상을 위해 더 엄격한 문법이 적용된다는 뜻이다.


- Constructor(생성자)

class Person {
	constructor(name){ // constructor는 이름을 바꿀 수 없다.
          // this는 클래스가 생성할 인스턴스를 가리킨다.
          // _name은 클래스 필드이다.
    	  this._name = name;
    }
}

constructor는 인스턴스를 생성하고 클래스 필드를 초기화하기 위한 특수한 메서드이다.

constructor는 클래스 안에 한 개만 존재할 수 있다. 2개 이상 있을 경우 Syntax Error가 발생하니까 주의하자.

부모 클래스의 constructor를 호출해야할 경우에는 super 키워드를 사용하면 된다.

클래스 필드의 선언과 초기화는 반드시 constructor 내부에서 실시한다.

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



- 메서드(Method) 정의

자바스크립트 클래스에서는 인스턴스에 상속되는지 여부에 따라서 메소드를 프로토타입 메서드, 스태틱 메서드로 나눈다.

프로토타입 메서드 (Prototype method)

인스턴스에 상속되어 인스턴스에서 직접 호출해 사용할 수 있는 메서드

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // 메서드
  calcArea() {
    return this.height * this.width;
  }
}

const square = new Rectangle(10, 10);

console.log(square.area); // 100

인스턴스에 상속되므로 Rectangle 클래스를 이용하여 생성된 square 인스턴스에서 area라는 메서드를 호출해서 사용할 수 있다.

정적 메서드 (Static method)

인스턴스에서 호출할 수 없는 메서드

정적 메서드는 클래스의 인스턴스가 아닌 클래스 이름으로 호출한다. 인스턴스를 생성하지 않아도 호출할 수 있다.

이것은 또한, 정적 메소드는 this를 사용할 수 없다는 의미도 된다. 일반 메소드 내에서 this는 앞으로 만들어질 클래스의 인스턴스를 가리키는데 정적 메서드는 인스턴스가 아닌 클래스 이름으로 호출하기 때문이다.

달리 말하면, 메서드 내부에서 this를 사용할 필요가 없는 메서드는 정적 메서드로 만들 수 있다는 이야기이다. Math 객체의 메서드처럼 애플리케이션 전역에서 사용할 유틸리티 함수를 생성할 때 주로 사용된다.


* 정적 속성(static property)

일반 클래스 프로퍼티와 유사하게 생겼으나 앞에 static이 붙는다는 점만 다르다.

class Article {
	static publisher = "David Kantor"
}

console.log(Article.publisher); // David Kantor

프로토타입 및 정적 메서드를 사용한 this 바인딩

프로토타입 메서드나 정적 메서드가 this 값 없이 호출될 때, this 값은 메서드 안에서 undefined가 된다. class 문법 안에 있는 코드는 항상 strict mode로 실행되기 때문에 "use strict" 명령어 없이도 그렇게 동작한다.

class Animal {
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}

let obj = new Animal();
obj.speak(); // the Animal object
let speak = obj.speak;
speak(); // undefined

Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined

클래스 상속

- extends를 통한 클래스 상속

extends 키워드는 클래스를 다른 클래스의 하위 클래스로 만들기 위해 사용된다.

아래 예제에서 Dog 클래스는 Animal 클래스의 하위 클래스가 된다.

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // super class 생성자를 호출하여 name 매개변수 전달
  }

  speak() {
    console.log(`${this.name} barks.`);
  }
}

let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.

- super 키워드

super 키워드는 인스턴스의 부모가 가지고 있는 메서드를 호출하기 위해 사용한다.

위 예제 코드에서 Dog 클래스는 Animal 클래스의 하위 클래스인데, Animal 클래스의 생성자나 메서드, this를 사용하려면 super가 먼저 호출되어야 한다.

class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }
  sayName() {
    console.log('Hi, I am a ', this.name + '.');
  }
}

class Square extends Polygon {
  constructor(length) {
    this.height; // 참조오류가 발생합니다. super가 먼저 호출되어야 합니다.

    // 여기서, 부모클래스의 생성자함수를 호출하여 높이값을 넘겨줍니다.
    // Polygon의 길이와 높이를 넘겨줍니다.
    super(length, length);

    // 참고: 파생 클래스에서 super() 함수가 먼저 호출되어야
    // 'this' 키워드를 사용할 수 있습니다. 그렇지 않을 경우 참조오류가 발생합니다.
    this.name = 'Square';
  }
}

클래스 재정의

클래스는 재정의될 수 없다. 재정의를 시도하면 Syntax Error가 발생한다.

참조

Classes - MDN

Class | PoiemaWeb

JavaScript 클래스 소개

코어 자바스크립트

0개의 댓글