Class는 객체를 생성하기 위한 템플릿이다. 클래스는 데이터와 이를 조작하는 코드를 하나로 추상화한다. 자바스크립트에서 클래스는 프로토타입을 이용해서 만들어졌지만 ES5의 클래스 의미와는 다른 문법과 의미를 가진다.
Class 정의
Class는 특별한 함수다 함수도 표현식, 선언식이 있는 것처럼 class문법 또한 표현식, 선언식으로 나눠져있다.
Class 선언
선언하기 위해서는 클래스의 이름과 함께 class 키워드를 사용해야 한다
class Rectangle {
constructor(height, widht) {
this.height = height;
this.width = width;
}
}
Hosting
함수 선언과 클래스 선언의 중요한 차이점은 함수의 경우 정의하기 전에 호출할 수 있지만(호이스팅 되어서 최상단으로 끌어올려진다), 클래스는 반드시 정의한 뒤에 사용할 수 있다는 점이다. 만약 호출하면 ReferenceError 발생
Class 표현
class 표현식의 이름은 클래스 body의 local scope에 한해 유효하다.
//이름이 없는 경우
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name); // Rectangle
let Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name); // Rectangl2
Class Body와 메서드 정의
class body는 중괄호 {} 로 묶여 있는 안쪽 부분이다. 이곳은 여러분이 메서드나 constructor와 같은 class 멤버를 정의
Strict mode
클래스의 본문(body)은 strict mode에서 실행된다. 즉, 여기에 적힌 코드는 성능 향상을 위해 더 엄격한 문법이 적용된다.
Constructor(생성자)
constructor 메서드는 class로 생성된 객체를 초기화하기 위한 특수한 메서드이다. ‘constructor’라는 이름을 가진 특수한 메서드는 클래스 안에 한 개만 존재할 수 있다. 여러 개를 사용하면 SyntaxError가 발생한다.
constructor는 부모 클새의 constructor를 호출하기 위해 super 키워드를 사용할 수 있다
프로토타입 메서드
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
//Getter
get area() {
return this.calcArea();
}
//메서드
calcArea() {
return this.height * this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
정적 메서드와 속성
static 키워드는 클래스를 위한 정적(static)메서드를 정의한다. 정적 메서드는 클래스의 인스턴스화 없이 호출되며, 클래스의 인스턴스에서는 호출할 수 없다. 정적 메서드는 어플리케이션을 위한 유틸리티 함수를 생성하는데 주로 사용된다. 반면, 정적 속성은 캐시, 고정 환경설정 또는 인스턴스 간에 복제할 필요가 없는 기타 데이터에 유용하다.
즉, static을 쓰면 Class의 인스턴스화 없이 호출되며 인스턴스화 시키더라도 호출 할 수 없다.
class foo {
constructor(name) {
this.name = name;
}
static sayHello() {
console.log('hello');
}
}
foo.sayHello(); //hello가 나온다
let temp = new foo();
temp.sayHello(); //VM2704:1 Uncaught TypeError: temp.sayHello is not a function
프로토타입 및 정적 메서드를 사용한 this 바인딩
메서드를 변수에 할당 한 다음 호출하는 것과 같이, 정적 메서드나 프로토타입 메서드가 this값 없이 호출될 때, this값은 메서드 안에서 undefined가 된다. 이 동작은 ‘use strict’ 명령어 없이도 같은 방식으로 동작하는데, class문법 안에 있는 코드는 항상 strict mode로 실행되기 때문이다.
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
obj.speak(); // the Aniaml object
let speak = obj.speak;
speak; // undefined
Animal.eat(); // class Animal
let eat = Animal.eat;
eat(); // undefined
위의 작성된 코드를 전통적 방식의 함수기반인 non-strict mode 구문으로 재작성하면, this 메서드 호출은 기본적으로 전역 객체인 초기 this값에 자동으로 바인딩 된다. Strict mode에서는 자동 바인딩이 발생하지 않는다. this값은 전달된 대로 유지된다.
function Animal() {}
Animal.prototype.speak = function() {
return this;
}
Animal.eat = function() {
return this;
}
let obj = new Animal();
let speak = obj.speak;
speak(); // global object
let eat = Animal.eat;
eat(); // global object
인스턴스 속성
인스턴스 속성은 반드시 클래스 메서드 내에 정의되어야 한다.
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
정적 (클래스사이드)속성과 프로토타입 데이터 속성은 반드시 클래스 바깥쪽에서 정의되어야 한다.
Rectangle.staticWidth = 20;
Rectangle.prototype.prototypeWidth = 25;
Public 필드 선언
자바스크립트의 필드 선언 문법을 사용해서 위의 예제는 아래와 같이 쓰여진다.
필드를 먼저 선언함으로서 클래스 정의는 self-documenting에 가까워졌고 필드는 언제나 존재하는 상태가 된다.
class Rectangle {
heigth = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}
Private 필드 선언
Private필드를 사용하면 아래와 같이 예제를 개선할 수 있다.
class Rectangle {
#heigth = 0;
#width;
constructor(height, width) {
this.#height = height;
this.#width = width;
}
}
클래스의 바깥에서 private필드를 접근하려고 하면 에러가 발생한다. private필드는 클래스 내부에서만 읽고 쓰기가 가능하다.
'JavaScript' 카테고리의 다른 글
Clean JavaScript(클린코드) (0) | 2022.07.31 |
---|---|
클래스 상속(Feat.extends) (0) | 2022.07.20 |
Nullish coalescing operator === ?? (0) | 2022.07.16 |
you are missing the point of promises 요약 (0) | 2022.06.24 |
Blocking vs Non-Blocking, Synchronous vs Asynchronous (0) | 2022.06.20 |