해당 포스팅에서는 ES2015 이후에 추가된 클래스에 대해 알아보았다.
1. 클래스란?
1) 생성자? 클래스?
(1) ES2015 이전, 생성자를 사용했다.
- ES2015 이전에는 클래스를 지원하지 않아, 생성자를 이용해 객체를 생성했다.
- 우리가 이러한 생성자를 사용한 이유는 객체의 형태(속성, 메소드)를 정의하기 위함이었다.
//생성자
function Animal({type, age}) {
//속성
this.type = type;
this.age = age;
}
//메소드
Animal.prototype.nameTag = function() {
return `이 동물의 종류는 ${type}이며, 나이는 ${age}이다.`;
}
new
를 사용해 객체를 선언하고 속성을 정의할 수 있다.
const animal = new Animal({type: '고양이', age: 12});
console.log(animal.nameTag()); // 이 동물의 종류는 고양이이며, 나이는 12이다
(2) ES2015, 클래스가 추가됐다.
- ES2015이전에는 생성자가 클래스 역할을 대신했지만, ES2015이후에는 클래스가 추가되었다.
class
키워드를 사용해 클래스를 선언하고 사용할 수 있게 되었다.- 클래스도 생성자와 동일하게, 객체의 형태(속성, 메소드)를 정의하기 위해 사용된다.
- 클래스 내부에서 선언하는 메소드가
prototype
에 저장된다.
class Animal {
constructor({type, age}) { //생성자
this.type = type;
this.age = age;
}
nameTag() { //클래스 내부에서 선언하는 메소드는 Animal.prototype에 저장
return `이 동물의 종류는 ${type}이며, 나이는 ${age}이다.`;
}
}
const animal = new Animal({type: '고양이', age: 12});
console.log(animal); // 이 동물의 종류는 고양이이며, 나이는 12이다
2) 생성자, 클래스의 차이
사용방법을 보니 클래스와 생성자의 차이가 거의 없는 거 같은데, 도대체 왜 추가된걸까? 클래스와 생성자의 차이점에 대해서도 알아보자
(1) 클래스는 함수로 호출될 수 없다.
- 생성자는 function을 사용해 선언되며, 그렇기에 함수처럼 호출할 수 있다.
function Animal1({ type, age }) {
console.log(type, age)
}
const animal1 = new Animal1({type: '고양이', age: 21}); // 고양이21
- 하지만 클래스는 함수처럼 호출해서 사용할 수 없다.
class Animal2 {
console.log(type, age) //error
}
(2) 클래스는 호이스팅이 불가하다.
- js의 특이한 점은 호이스팅이 가능하다는 것이다.
- 그럼 호이스팅은 무엇이냐? 변수선언이 해당 함수의 최상단으로 끌어 올려지는 걸 말한다.
- 우리는 사용하고자 하는 변수를 우선 선언하고 그다음에 그 변수를 사용한다.
const hello = 'world'; //변수 우선 선언
console.log(hello); //선언한 변수 사용
- 그런데 만약 변수 출력문보다, 변수 선언문을 나중에 작성했다면?
console
입장에서는hello
변수가 선언되지 않았으니 에러가 떠야할 듯 하다.
console.log(hello); //hello 변수 사용?
const hello = 'world'; //출력문보다 늦게 변수 선언
- 그러나
js
에서는 변수선언문을 나중에 작성해도, 해당 변수 사용이 가능하다! - 그 이유는
js
에서는 호이스팅이 발생하므로, 나중에 선언한 변수에도 접근할 수 있기 때문이다.
console.log(hello); //hello 변수 사용가능!
const hello = 'world'; //출력문보다 늦게 변수 선언했지만...
그럼 js의 특징인 호이스팅은 클래스에도 사용할 수 있을까? 답은 사용할 수 없다!
class Animal {
constructor({ type, age }) {
this.type = type;
this.age = age;
}
print() {
console.log(this.type, this.age)
}
}
animal.print(); //error
const animal = new Animal({type: '고양이', age: 12})
(3) 클래스 메소드에선 super 키워드를 사용할 수 있다.
- super 키워드는 클래스의 상속과 관련된 내용이다.
- 이 부분은 2.클래스 사용법 의 상속에서 자세히 알아보자!
2. 클래스 사용법
1) 클래스의 형태
class
키워드를 이용하여 클래스를 정의한다.- 클래스의 역할을 인스턴스(객체를 메모리에 할당한 것)를 생성하는 것이다.
- 클래스의
constructor
메소드는 초기화 역할을 한다.
class Person {
constructor() {
console.log('실행')
}
}
- 만약 우리가
Person
클래스로 인스턴스를 만들면, 먼저 Person의constructor
가 실행된다.
new Person(); //실행
- 클래스를 사용해 객체의 속성, api 등을 설정할 수 있다.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const lili = new Person('lili', 40); // lili는 Person클래스의 인스턴스
console.log(lili); // Person {name: 'lili', age: 40}
2) 메소드
(1) 메소드 선언
- 메소드를 클래스 내부에 선언할 수 있다.
- 클래스 내부에 선언된 메소드는 해당 클래스의
prototype
에 저장된다.
class Animal {
test() {
return 'test print'
}
}
(2) 가변적인 메소드명
- 만약 가변적인 메소드명이 필요하다면, 대괄호(
[메소드명]
)로 메소드를 선언하면 된다. - 단, 메소드명을 선언한 변수는 클래스보다 우선 선언되어야 한다.
const methodName = 'test'; //메소드명 우선 선언
class Animal {
constructor({ type, age }) {
this.type = type;
this.age = age;
}
[methodName]() {
console.log('hello~')
}
}
const animal = new Animal({type: '고양이', age: 12});
animal.test(); //hello~
(3) getter, setter
- getter, setter는 객체 속성값에 접근하는 함수이다.
- getter를 이용해 속성값을 읽고, setter를 이용해 속성값을 편집할 수 있다.
- 클래스 내부 메소드에도 getter, setter를 사용할 수 있다.
class Animal {
constructor({ type, age }) {
this._type = type;
this._age = age;
}
get type() { // getter
return this._type;
}
set type(newType) { // setter
this._type = newType;
}
}
const animal = new Animal({type: '고양이', age: 12});
console.log(animal.type); // 고양이
animal.type = '멍멍이';
console.log(animal.type); // 멍멍이
(4) 정적 메소드
- 메소드 앞에
static
키워드를 붙이면, 정적 메소드가 된다.
class Animal {
static print() {
console.log('test')
}
}
- 클래스 내부 메소드에서 정적 메소드 방식을 주로 사용하며,
- 인스턴스에서는 호출할 수 없고 클래스 생성자로만 호출 가능하다.
const animal = new Animal(); // 인스턴스 생성(Animal객체를 메모리에 할당)
animal.print(); // error
Animal.print(); // test
3) 상속
(1) 클래스 상속
- 클래스는 다른 클래스를 상속받아 재사용할 수 있다.
- 만약 Child가 Parent 클래스를 상속 받으려면
자식클래스 extends 부모클래스
을 사용하면 된다.
class Parent {
...
}
class Child extends Parent {
...
}
(2) 상속의 장점
- 자식 클래스(A)가 부모 클래스(B)를 상속 받으면, A는 B의 정적 메소드와 속성을 사용할 수 있다.
class Parent {
static test = '123';
static print() {
console.log('print');
}
}
class Child extends Parent {}
Child.print(); // print
console.log(Child.test) // 123
- 또한, A의 인스턴스에서 B의 인스턴스 메소드와 속성을 사용할 수 있다.
class Parent {
constructor(test) {
this.test = test;
}
print() {
console.log('print');
}
}
class Child extends Parent {}
const child = new Child(123);
child.print(); // 123
console.log(child.test) // 123
(3) super키워드
- 만약 자식 클래스(A)에 부모 클래스(B)와 동명의 속성이 있는 경우 어떻게 해야할까?
- 자식 클래스에
getColor
라는 메소드가 있는데, 부모에도 동일한 이름의 메소드가 존재하면, - 자식 클래스의 메소드를 사용하게 된다. (부모 클래스의 메소드는 무시됨)
class Apple {
getColor() {
return '나는 빨강';
}
}
class Orange extends Apple {
getColor() {
return '나는 주황';
}
}
const orange = new Orange();
console.log(orange.getColor()); //나는 주황
하지만 상속을 한다는 건 부모의 속성, 메소드를 사용하고 싶은 의도가 있는 것이다.
만약, 부모 클래스 값을 이용하고 싶다면 우리는super
키워드를 사용하면 된다.
- 생성자 내부에
super()
를 호출하면, 부모 클래스의 생성자가 호출된다.
class Apple {
constructor(name) {
this.name = name;
}
}
class Orange extends Apple {
constructor(name, type) {
super(name); //부모의 constructor 사용 가능
this.type = type;
}
print() {
console.log( `${this.name} ${this.type}`);
}
}
const orange = new Orange('orange', 'fruit');
orange.print() // orange fruit
- 정적 메소드 내부에서
super.prop
을 사용하면 부모 클래스의 정적 속성에 접근할 수 있다.
class Apple {
static print() {
return 'apple';
}
}
class Orange extends Apple {
static print() {
return super.print() + ' orange';
}
}
console.log(Orange.print()); //apple orange
- 인스턴스 메소드 내부에서
super.prop
을 사용하면 부모 클래스의 인스턴스 속성에 접근할 수 있다.
class Apple {
print() {
return 'apple';
}
}
class Orange extends Apple {
print() {
return super.print() + ' orange';
}
}
const orange = new Orange();
console.log(orange.print()); //apple orange
참고자료
아래 링크로 가면 더 자세히 알 수 있습니다~
반응형
'개발 기술 > 개발 이야기' 카테고리의 다른 글
프로토타입 (feat. 매운 맛🔥) (0) | 2021.11.04 |
---|---|
프로토타입이란? (feat. 순한 맛 🌝) (0) | 2021.11.02 |
블록 스코프, 함수 스코프의 차이 (javascript) (0) | 2021.10.30 |
scroll 방향 감지하기 (with. js) (0) | 2021.10.29 |
SOLID 윈칙 (solid principle) (0) | 2021.10.25 |
댓글