클래스는 ES6 에서 추가된 키워드로 기존의 prototype 기반의 방식을 좀 더 명료하게 사용하기 위한 것이며, 새로운 객체지향 상속 모델을 제공하는 것은 아니다.
클래스 정의
함수와 마찬가지로 선언적 방식과 변수에 할당하는 방식을 사용할 수 있다. 하지만 클래스는 함수와 달리 호이스팅이 일어나지 않는다.
1
2
3
4
5
6
7
//선언적 방식
class A {}
new A();
//변수에 할당
const B = class {};
new B();
생성자(constructor)
클래스의 인스턴스를 생성할때 constructor 가 실행되는데 이 안에 필요한 초기화 작업을 구현해주면 된다. 별도로 구현하지 않는 경우 기본 constructor 가 실행된다.
1
2
3
4
5
6
7
class Person {
constructor(name) {
this.name = name;
}
}
const me = new Person('Changhee');
클래스필드
지금까지 객체의 멤버변수를 선언하기 위해 생성자 함수에서 멤버변수를 생성해주었는데, 클래스에서는 멤버 변수를 선언할 때 자바의 클래스처럼 클래스 필드를 통해 좀 더 명료하게 선언할 수 있다.
클래스 필드를 사용하기 위해서는 크롬 74 버전 이상, Node.js 의 경우 12.0.0 버전 이상 이 필요하며, 클래스 필드에 아무런 접두사를 붙이지 않으면 public, #을 붙이면 private 으로 동작한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person {
name;
#privateProp = 'private!!';
constructor(name) {
this.name = name;
}
}
const me = new Person('Changhee');
console.log(me.name); //Changhee
console.log(me.privateProp); //undefined
console.log(me.#privateProp);
/*
console.log(me.#privateProp);
^
SyntaxError: Private field '#privateProp' must be declared in an enclosing class
*/
getter, setter
get, set 키워드를 사용하여 getter 함수와 setter 함수를 사용할 수 있는데, 아래의 코드처럼 함수를 호출 할 때 함수의 이름을 참조하면서 값을 주면 setter 함수가 호출되고 참조만 하면 getter 함수가 호출된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person {
_name;
get name() {
return this._name;
}
set name(name) {
this._name = name;
}
}
const p = new Person();
p.name = 'Changhee'; // setter 가 실행된다.
console.log(p.name); // getter 가 실행된다.
getter, setter 함수를 통해 private 필드에도 접근이 가능해진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
#privateProp;
get privateProp() {
return this.#privateProp;
}
set privateProp(value) {
this.#privateProp = value;
}
}
const a = new A();
a.privateProp = 'private!!';
console.log(a.privateProp); //private!!
Static
static 키워드를 사용하여 클래스의 인스턴스를 생성하지 않아도 전역적으로 접근할 수 있는 멤버변수나 함수를 생성할 수 있다.
1
2
3
4
5
6
7
8
9
class A {
static staticProp = 'static!!';
static hello() {
console.log('static function!!!');
}
}
console.log(A.staticProp); //static!!
A.hello(); //static function!!!
static 키워드가 붙은 필드는 클래스 당 한 번만 존재하도록 하기 위해서 인스턴스에는 포함되지 않는다. 반대로 static 이 아닌 필드는 인스턴스에서만 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
static staticProp = 'static!!';
nonStaticProp = 'nonStatic!!';
static hello() {
console.log('hello!!');
}
}
console.log(A); // [Function: A] { staticProp: 'static!!' }
A.hello(); // hello!!
const a = new A();
console.log(a); // A { nonStaticProp: 'nonStatic!!' }
a.hello(); // error: a.hello is not a function
name 이란 이름의 클래스필드를 static 으로 선언하면 해당 클래스의 이름으로 사용된다.
1
2
3
4
5
Class A {
static name = "Class_Name"
}
console.log(A); //[Function: Class_Name] { name: 'Class_Name' }
상속
extends
상속은 extends 키워드를 사용한다. 상속받은 멤버변수나 함수를 오버라이딩 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Parent {
name = 'ParentName';
hello() {
console.log('Parent!!');
}
}
class Child extends Parent {
hello() {
console.log('Child');
}
}
const c = new Child();
console.log(c.name); //ParentName
c.hello(); //Child
super
자식 클래스에서 super 를 사용하여 부모 클래스를 호출할 수 있다. 만약, 자식 클래스에 constructor 가 있다면, this 를 사용하기 전 super() 를 호출해야 한다. 그렇지 않으면 아래와 같은 에러가 발생한다.
ReferenceError: M ust call super constructor in derived class before accessing ‘this’ or returning from derived constructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Parent {
name;
constructor(name) {
this.name = name;
}
hello() {
console.log(`name: ${this.name}`);
}
}
class Child extends Parent {
category;
constructor(name, category) {
super(name);
this.category = category;
}
hello() {
console.log(`name: ${this.name}, category: ${this.category}`);
}
}
const c = new Child('Apple', 'Food');
c.hello(); //name: Apple, category: Food
참고자료
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_fields
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes