클래스 기반 객체지향언어에 익숙한 개발자들을 위해서
ECMAScript 6에서 새롭게 클래스가 도입되었다.
class MyClass {
// 여러 메소드를 정의할 수 있음
constructor() { ... }
method1() { ... }
method2() { ... }
method3() { ... }
...
}
const foo = new MyClass(); // MyClass 인스턴스 생성
Class
키워드를 사용하여 클래스를 정의한다.
constructor
는 인스턴스를 생성하고 초기화하기 위한 생성자 메소드이다.(constructor는 클래스 내에 한개만 존재 가능)
method
는 클래스 몸체에만 선언할 수 있으며 여러개가 존재할 수 있다.
new 연산자와 함께 클래스 이름을 호출
하면 클래스의 인스턴스가 생성된다.
(new MyClass() 호출 시, 생성자 메소드 constructor()가 자동으로 호출되며 객체를 초기화한다.)
클래스 또한 호이스팅이 일어나지만 let, const 키워드와 같은 방식으로 호이스팅이 일어나기 때문에 선언문 이전에 참조할 수 없다.
console.log(MyClass); // ReferenceError: Cannot access 'MyClass' before initialization class MyClass {}
함수처럼 Class도 표현식으로 정의할 수 있다.
let User = class {
sayHi() {
console.log("Hello");
}
};
const foo = new User();
다만, Class 표현식에 이름을 붙이는 경우는 Class 내부에서만 사용이 가능하다.
let User = class MyClass {
sayHi() {
console.log(MyClass);
// MyClass라는 이름은 오직 클래스 안에서만 사용 가능
}
};
new MyClass(); // ReferenceError: MyClass is not defined
리터럴을 사용해 만든 객체처럼 클래스도 접근자 프로퍼티(accessor property)
를 이용하여 값을 획득(get)하고 설정(set)한다.
객체의 프로퍼티를 객체 바깥에서 직접 조작하는 행위는 데이터의 유지 보수성을 해치는 주요한 원인이기 때문에 접근자 프로퍼티로 조작하는 것이 좋다고 한다.
class User {
constructor(name, surname){
this.name = name;
this.surname = surname;
}
get fullName() {
return `${this.name} ${this.surname}`;
}
set fullName(value) {
[this.name, this.surname] = value.split(' ');
}
};
const foo = new User('jiseong', 'Son');
console.log(foo.fullName); // jiseong Son
foo.fullName = 'Brendan Eich';
console.log(foo.fullName); // Brendan Eich
extends
키워드는 부모 클래스를 상속받는 자식 클래스를 정의 할 때 사용된다.
// 부모 클래스
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello ${this.name}`);
}
}
// 자식 클래스
class Student extends Person {
}
let student1 = new Student('jiseong');
student1.greet(); // Hello jiseong
자바스크립트도
오버라이딩
오버로딩
구현이 가능하다.
오버라이딩(Overriding)
상위 클래스가 가지고 있는 메소드를 하위 클래스가 재정의하여 사용하는 방식.
오버로딩(Overloading)
매개변수의 타입 또는 갯수가 다른, 같은 이름의 메소드를 구현하고 매개변수에 의해 메소드를 구별하여 호출하는 방식.
자바스크립트는 오버로딩을 지원하지 않지만 arguments 객체를 사용하여 구현할 수는 있다.
super
키워드는 부모 클래스의 생성자 메서드를 호출할 때 사용되며, this 키워드가 사용되기 전에 호출되어야 한다. (부모 클래스를 참조할 때도 사용)
// 부모 클래스
class Person {
constructor(name) {
console.log('2');
this.name = name;
}
greet() {
console.log(`Hello ${this.name}`);
}
}
// 자식 클래스
class Student extends Person {
constructor(name) {
console.log('1');
// this.name; // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
super(name); // call the super class constructor and pass in the name parameter
console.log('3');
}
}
let student1 = new Student('jiseong');
student1.greet(); // 1 2 3 Hello jiseong
ES6에서 새롭게 추가된 Class는 사실 함수
이다.
class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(this.name);
}
}
console.dir(User);
Prototype에서 함수만이 prototype 프로퍼티를 가질 수 있다고 하였는데 Class도 가지고 있는 것을 볼 수 있다. 이는 사실 Class도 함수이기 때문이다.
console.log(typeof User); // function
좀더 알아보기 위해 class User {...}
를 그림으로 나타내 보았다.
sayHi같은 클래스 내에서 정의한 메서드는 User.prototype에 저장되어 있고 User의 __proto__
또한 function인 것을 확인 할 수 있었으며 일부 사람들이 Class를 기존 프로토타입 기반 패턴의 문법적 설탕(Syntactic sugar)이라고 보는 이유가 위와 같은 이유일 것이라 생각한다.