안녕하세요. 이번에도 자바스크립트 객체 생성을 다루어 보려고합니다.
객체 생성 파트는 이번이 마지막이 될 것 같습니다.
ES6에서 추가된 새로운 문법 중에 class를 통해서 객체를 생성하는 기능이 추가되었습니다.
새로운 객체 생성 방식을 살펴보고 Object.create() 방식과 비교해보겠습니다.
1. class 객체 생성 기본형태
class test1 {
a;
b = 2;
constructor(paramB) {
this.a = 1;
this.b = paramB;
}
// 사용할 메소드 선언
getA() {
return this.a;
}
getB() {
return this.b;
}
...
}
let t1 = new test1();
console.log(t1); // 아래 이미지 참조
let t2 = new test1(20);
console.log(t2); // 아래 이미지 참조
일단 class 객체 생성 방식은 객체 내부에서 사용할 프로퍼티(a, b)와 메소드를 선언합니다.
getA(), getB()과 같은 메소드를 선언해도 되고 안해도 상관은 없습니다. (optional)
그리고 가장 중요한 부분이 생성자(constructor) 입니다.
생성자를 선언하지 않으면 해당 클래스로 객체를 생성 시, 빈 객체가 생성됩니다.
그리고 생성자에 인자를 받아서 프로퍼티를 세팅하는 방식으로 선언 시에 인자를 넘기지 않으면 값이 undefined됩니다.
2. class 프로퍼티의 getter, setter
- 데이터 프로퍼티(data property) : 값을 저장하기 위한 프로퍼티. 일반적으로 사용하는 프로퍼티는 데이터 프로퍼티입니다. 데이터 프로퍼티 조작 방법에 대해선 모두 알고 계실 것이라 생각합니다.
- 접근자 프로퍼티(accessor property) : 값이 없음. 프로퍼티를 읽거나 쓸 때 호출하는 함수를 값 대신에 지정할 수 있는 프로퍼티입니다. 접근자 프로퍼티의 본질은 함수인데, 이 함수는 값을 획득(get)하고 설정(set)하는 역할을 담당합니다. 그런데 외부 코드에서는 함수가 아닌 일반적인 프로퍼티처럼 보입니다.
접근자 프로 퍼티는 getter, setter 메소드로 표현하기에, 따로 선언할 필요가 없습니다. 프로 퍼티에 접근하는 것은 getter, setter에 의해서 이뤄집니다.
class test1 {
cat;
constructor(a) {
this.cat = a;
}
get catFoot() {
return this.cat * 4;
}
set catFoot(param) {
if(param) {
this.cat = param/4;
} else {
return;
}
}
}
let t1 = new test1(10);
console.log(t1.cat); // 10
console.log(t1.catFoot); // 40
t1.catFoot = 16;
console.log(t1.cat); // 4
console.log(t1.catFoot); // 16
위에 예제를 보시면, 프로퍼티 cat은 정의했지만, catFoot은 정의하지 않고 getter, setter 메소드로 정의했습니다.
new 지시어를 통해 인스턴스를 생성하면서 cat 초기값을 10으로 설정하면, setter 메소드에 의해 catFoot은 40의 값을 가집니다.
또한 catFoot을 16으로 설정하면 getter 메소드에 의해 cat은 4의 값으로 설정됩니다.
이렇듯 접근자 프로퍼티 getter, setter는 데이터 프로퍼티의 값을 세팅하거나 데이터 프로퍼티의 값을 연산하여 보여줄 때 쓰기 좋습니다.
cf) getter, setter는 delete 지시어로 삭제 가능합니다. delete test1.catFoot
3. class 객체 상속
개인적으로 class 객체의 존재 이유는 상속이 쉽다는 점인 것 같습니다. Object.create()를 통해 객체를 만들어 상속을 해서 쓰려면 코드가 길어져서 불편했습니다.
하지만 class 객체의 상속은 보다 용이합니다. 자바의 클래스 상속과 거의 유사하며, 다중 상속이 불가능합니다. (interface mixin 방식으로 구현한다면 다중 상속도 가능하긴 합니다.)
class test1 {
a; b;
constructor(a, b) {
this.a = a;
this.b = b;
}
getA() {
return this.a;
}
getB() {
return this.b;
}
}
class test2 extends test1 {
c;
constructor(a, b, c) {
super(a, b);
this.c = c;
}
getC() {
return this.c;
}
}
let t1 = new test2(1,2,3);
console.log(t1); // 아래 이미지 참조
test1이 부모 클래스(객체)이며, test2가 test1을 상속받는 코드입니다.
class test2에서 extends 지시어를 쓰면 test1을 상속받을 수 있습니다.
주의하실 점은 생성자(constructor)와 super() 메소드 입니다.
test2(자식 메소드)에서 constructor 선언 시 꼭 super() 메소드를 호출해야합니다.
super() 메소드는 상속받은 부모를 호출하는 역할을 합니다.
즉, super를 통해 부모 객체(클래스)의 속성, 메소드가 연결됩니다.
또한 부모 객체에 선언한 constructor의 인자를 super 메소드로 넘겨주어야합니다.
4. 추상 클래스와 추상 메소드
자바에서 흔히 들어본 추상 클래스와 추상 메소드를 자바스크립트에서 사용할 수 있습니다.
부모 클래스에서 추상 메소드를 선언하여, 상속받는 자식 클래스에서 추상 메소드를 오버라이드해서 구체적으로 정의할 때 추상 클래스와 추상 메소드가 사용됩니다.
typeScript에서는 명시적으로 추상 클래스와 추상 메소드를 만드는 지시어가 존재합니다.
하지만 ES6에서는 명시적으로 추상 지시어(abstract) 선언할 수 없습니다.
그래서 부모 클래스에 빈 메소드를 정의하고, 자식 클래스에서 오버라이드해서 사용하는 방식으로 구현하면 됩니다.
class test1 {
a;
b;
constructor(a, b) {
this.a = a;
this.b = b;
}
...
sum() {};
}
class test2 extends test1 {
c;
constructor(a, b, c) {
super(a, b);
this.c = c;
}
...
sum() {
return this.a + this.b + this.c;
}
}
let t1 = new test2(1,2,3);
console.log(t1.sum()); // 6
sum() 이란 함수를 자식 메소드에서 오버라이드해서 정의했습니다.
아쉽게도 부모 클래스에서 정의한 추상 메소드를 자식 클래스에서 반드시 선언해야 하는 강제성이 없습니다.
typeScript에서는 이 점이 보완, 확장되어 추상 메소드를 반드시 선언해야하는 강제성을 지닙니다.
추상 클래스와 추상 메소드를 제대로 쓰려면, typeScript로 코드를 작성해야할 것 같습니다.
자바스크립트에서 추상 클래스와 추상 메소드라는 것이 있다는 것만 알아두시면 될 것 같습니다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/get
'javaScript' 카테고리의 다른 글
javaScript - 비동기 함수 동기식으로 실행하기(Promise와 async) (0) | 2021.07.12 |
---|---|
javaScript - 스프레드 오퍼레이터(Spread Operator) (0) | 2021.07.12 |
javaScript - 유용한 메소드 모음 (0) | 2021.07.07 |
javaScript - 객체 생성 Object.create() (0) | 2021.07.01 |
javaScript - 프로토타입(prototype) 객체 (0) | 2021.06.29 |
댓글