이전 글에서 살펴보았듯이, 자바스크립트는 프로토타입을 사용하여 객체 지향 프로그래밍을 할 수 있다. ES6에서 도입된 클래스는 자바나 C 언어의 클래스 문법과 유사하게 객체 생성할 수 있도록 한다. 자바스크립트의 클래스는 실제로는 함수처럼 동작하며, 기존의 프로토타입 생성 방식과 다르지 않다. 따라서 클래스를 문법적 양념(syntactic sugar)일 뿐이라고 말하기도 한다.
클래스가 도입된 이유
function Student(name,age){
this.name = name
this.age = age
}
const student1 = new Student('king',20) // {'name': 'king', 'age': 20}
const student2 = Student('king', 20); // undefined
위 Student는 일반 함수이고, new 키워드를 붙여 호출하면 this를 반환하는 생성자 함수로 동작한다. 이 때 주의할 점은 new를 붙여 호출하지 않으면, 일반함수처럼 동작한다는 것이다. 자바스크립트는 함수를 일반 함수 또는 생성자 함수처럼 호출하는 두 가지 방식을 모두 허용하며, 이는 혼란을 초래할 수 있다. 이에 반해 클래스에서는 new 연산자 없이 호출하면 에러가 발생한다. 따라서 원하는 생성자의 의도로만 Student 인스턴스를 생성할 수 있다는 장점이 있다.
클래스를 정의하는 방법
class Student{
constructor(name,age){
this.name = name
this.age = age
}
getAge(){
return this.age;
}
static hello(){
console.log("hello")
}
}
const student1 = new Student('king',20)
console.log(student1.getAge()) // 20
console.log(Student.hello())
- constructor를 정의하여 인스턴스를 생성하면서 프로퍼티 값을 초기화할 수 있다.
- class 내부에서 프로토타입 메서드를 정의할 수 있다.
- static 키워드를 사용해서 정적 메서드를 정의할 수 있고, 정적 메서드는 클래스에 직접 접근하여 사용할 수 있다.
- console.log(typeof Student)를 한다면 function이 출력된다. 클래스는 자바스크립트에서 생성자 함수이기 때문이다.
이를 함수 및 프로토타입 기반으로 작성하면 다음과 같다.
var Student = (function() {
function Student(name, age){
this.name = name;
this.age = age;
}
Student.prototype.getAge = function() {
return this.age;
}
Student.hello() = function() {
console.log("hello");
}
return Student;
}();
private 필드
class Student {
#name= '';
constructor(name) {
this.#name = name;
}
}
const student1 = new Student('me');
console.log(me.#name); // SyntaxError
#을 사용하여 private 필드를 정의할 수 있다. 클래스에서 필드를 정의하면 기본적으로 공개(public)이기 때문에 외부에서 바로 접근할 수 있다. private 필드는 클래스 내부에서만 참조할 수 있고, 인스턴스나 자식 클래스에서는 접근할 수 없다.
상속
상속이란, 기존 클래스를 상속받아 새로운 클래스를 확장하여 정의하는 것을 말한다. 상속을 사용하면 클래스의 속성 일부 또는 전체를 재사용할 수 있다는 점에서 유연하다.
class DateFormatter extends Date {
getFormattedDate() {
return `${this.getDate()}-${this.getMonth()+1}-${this.getFullYear()}`; // 1
}
}
const date1 = new DateFormatter('August 19, 1975 23:15:30'); // 2
console.log(date1.getFullYear()) // 3
console.log(date1.getFormattedDate()); // 4
// Expected output: "19-Aug-1975"
다음 DateFormatter이라는 클래스는 Date라는 클래스를 상속해서 만든 클래스이다. 다음을 확인할 수 있다.
- Date 클래스를 상속한 DateFormatter는 상위 클래스의 메서드를 활용할 수 있다.
- new 키워드를 사용하여 인스턴스를 생성하면 상위 클래스의 생성자가 호출된다.
- 인스턴스에서 getFullYear()를 접근하면 프로토타입 체인에 의해서 먼저 DateFormatter 메서드가 있는 지 확인하고, 존재하지 않을 경우에는 상위 프로토타입인 Date에서 getFullYear메서드가 있는 지 확인한다. 존재하므로, 해당 메서드를 실행한다. 따라서 인스턴스는 상위 클래스의 메서드를 활용할 수 있다.
- Date의 getFormattedDate 메서드가 오버라이드 되었다.
클래스와 함수에서 다른 점
- 클래스는 new 연산자 없이 호출하면 에러가 발생한다.
- extends와 super 키워드를 제공한다.
- 클래스는 호이스팅이 발생하지 않는 것처럼 동작한다. (모든 변수, 함수, 클래스 선언은 호이스팅 발생하는 것이 맞다. 그러나 let, const와 유사하게 class 선언시점까지는 일시적 사각지대에 빠져 접근할 수 없다.)
- 클래스 내의 모든 코드는 암묵적으로 strict mode가 지정되어 실행되며 strict mode를 해제할 수 없다.
참고
'책정리 > Deep Dive Javascript' 카테고리의 다른 글
자바스크립트, html로 짠 코드가 브라우저에서 렌더링되는 과정 (0) | 2023.12.03 |
---|---|
자바스크립트의 배열은 알고보니 객체였다? (0) | 2023.12.02 |
자바스크립트 this 동적 바인딩 총정리 (0) | 2023.11.27 |
자바스크립트는 프로토타입 기반 언어이다 (1) | 2023.11.26 |
객체 프로퍼티 접근, 변경 시 내부 동작 방식 (Javascript) (1) | 2023.11.25 |