Table of Contents
- 자바스크립트는 프로토타입 기반 객체지향 언어이다
- ES5에서는 클래스 없이도 생성자 함수와 프로토타입을 통해 객체지향 프로그래밍을 구현할 수 있다
- 하지만 클래스 기반 언어에 익숙한 프로그래머들을 위해 ES6에서 클래스를 도입했다
클래스와 생성자 함수의 차이
- 클래스는
new
연산자 없이 호출하면 에러가 발생한다. 생성자 함수는new
연산자 없이 호출하면 일반 함수로서 호출된다 - 클래스는 상속을 지원하는
extends
와super
키워드를 제공한다 - 클래스는 호이스팅이 발생하지 않는 것처럼 동작한다
클래스
- 클래스는
class
키워드를 사용해 정의한다 - 클래스는 값처럼 사용할 수 있는 일급 객체인 함수이다 (런타임 이전에 먼저 평가되어 함수 객체를 생성한다)
- (
class Person {}
이런식으로Person
클래스를 정의하면 평가 시점에Person
이라는 식별자에, 생성자 역할을 하는 함수 객체를 생성한다) - 클래스 몸체에서는
constructor
, 프로토타입 메서드 그리고 정적 메서드 이렇게 3개의 메서드만 보통 정의한다 - (클래스 필드도 정의할 수 있지만 ECMAScript의 정식 표준 사양에는 포함되지 않았다)
class Person {
constructor(name) {
this.name = name
}
// 프로토타입 메서드
sayHi() {
console.log(`Hi! My name is ${this.name}.`)
}
// 정적 메서드
static sayHello() {
console.log('Hello!')
}
}
Person.sayHello()
const me = new Person('Lee')
me.sayHi()
메서드
- 클래스에서 정의한 메서드는
function
키워드를 생략한 메서드 축약 표현을 사용해야 한다 - (일반 함수로 정의하면 constructor가 된다 -> 불필요하게
prototype
프로퍼티를 가지게 된다) - (그래서 non-constructor로 하기 위해 축약 표현만 허용한다)
constructor
- 인스턴스의 프로퍼티는 클래스 몸체에서도 정의할 수 있다
- 하지만 인스턴스의 프로퍼티를 외부에서 전달해 초기화 하고 싶으면 반드시
constructor
메서드를 사용해야 한다 constructor
는 인스턴스를 생성하고 초기화하기 위한 특수한 메서드이다constructor
는 클래스 내에서 최대 한 번만 정의할 수 있다- 암묵적으로
this
, 즉 인스턴스를 반환한다 (별도의 반환문이 없어야 한다)
class Person {
constructor(name, address) {
this.name = name
this.address = address
}
}
const me = new Person('Lee', 'Seoul')
프로토타입 메서드
- 클래스 몸체에서 정의한 메서드는 인스턴스의 프로토타입에 존재하는 프로토타입 메서드가 된다
- 인스턴스는 프로토타입 메서드를 상속받아 사용한다
Object.getPrototypeOf(me) === Person.prototype // true
Object.getPrototypeOf(Person.prototype) === Object.prototype // true
me.constructor === Person // true
정적 메서드
- 클래스에서는 메서드에
static
키워드를 붙이면 정적 메서드(클래스 메서드)가 된다 - 정적 메서드는 클래스에 바인딩된 메서드가 된다
- 인스턴스를 생성하지 않아도 호출할 수 있다
- 클래스는 인스턴스의 프로토타입 체인상에 존재하지 않기 때문에, 정적 메서드는 인스턴스로 호출할 수 없다
- 정적 메서드 내부의
this
는 인스턴스가 아닌 클래스를 가리킨다
class Person {
static sayHi() {
console.log('Hi')
}
}
- 클래스의 주요 목적이 인스턴스 생성이 아닌, 네임스페이스를 만들기 위한 용도인 경우, 정적 메서드를 많이 사용한다
- 아래 예제를 보면 똑같은
sayHi
메서드이지만Person
,Animal
클래스가 네임스페이스 역할을 하기 때문에 구분된다
Person.sayHi()
Animal.sayHi()