oris9
[Javascript] 클래스를 이해하고 모듈화 해보기 본문
클래스 개념 이해하기
1. 클래스의 개념과 특징
클래스는 객체를 만들기 위한 설계도로,
프로토타입 성질을 좀 더 쉽게 사용하기 위한 ES6에 추가된 문법적 부가기능이다.
Prototype과 달리 constructor라는 함수가 별도로 존재한다.
클래스 선언은 호이스팅 되지 않는다는 특징이 있다.
낮은 응집도와 낮은 결합도를 가진 클래스를 설계해야한다.
* 응집도 (한 모듈 내부의 요소들이 서로 관련되어 있는 정도)
* 결합도 (서로 다른 모듈(클래스) 간 상호 의존 정도
적절하게 관심사를 분리하여 각 항목이 높은 독립성을 가지도록 설계해야한다.
오픈소스 유저 라이브러리등을 참고해서 좋은 코드를 작성하기
2. Getter , Setter
클래스 내부에서 쓰이는 일종의 메서드로,
Getter는 객체의 속성(property) 값을 반환하는 메서드이며, Setter는 객체의 속성 값을 설정, 변경하는 메서드이다.
***
Getter와 Setter은 이론적인 개념으로서
보통 위와 같이 get프로퍼티명(), set프로퍼티명() 형식으로 메서드 이름을 짓는 식으로 약속하여 사용하지만,
ES6 최신 자바스크립트부터는 Getter와 Setter를 간단하게 정의할 수 있는 문법이 별도로 추가되었다.
객체 리터럴 안에서 속성 이름 앞에 get 또는 set 키워드만 붙여 Getter와 Setter를 정의할 수 있게 되었다.
(아래에선 키워드를 붙여 getter, setter를 정의하는 코드로 설명 진행)
아래 코드는 getter와 setter를 이용해서 age에 음수 입력을 방지하는 코드이다.
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get age() {
return this._age; // 만일 Getter만 선언하고 Setter은 선언 안했을시, 접근자 프로퍼티는 getter 메서드만 가지고 있기 때문에 값을 할당하려고 하면 에러가 발생되게 된다.
}
set age(value) {
// if(value < 0){
// throw Error('올바른 나이 범위를 입력해주세요')
// }
this._age = value < 0 ? 0 : value; // 이때 this.age와 같이, 데이터 프로퍼티명과 접근자 프로퍼티명이 동일할경우 setter가 호출될때 재귀가 되어 무한루프에 빠지게된다
}
}
const user1 = new User('Steve', 'Job', -1)
console.log(user1.age) // 0
위 코드처럼 getter와 setter를 이용하면,
age를 호출할 때 설정한 getter,setter 메서드를 거쳐서 age를 호출하게 된다.
따라서 객체 내부 속성에 직접 접근할 수 없게된다. = 객체의 정보은닉이 가능해져 보안성 ⬆️ 코드의 안전성과 유지보수성 ⬆️
또한 중간에 메서드를 거쳐서 age를 호출하므로, 위 코드와 같이 옳지 않은 값을 넣으려고 할 때 이를 방지해줄 수 도 있다.
이 때 get , set 키워드를 통해 붙인 메서드는 가상프로퍼티로 생성되게 된다. (읽고 쓸 수는 있지만, 실제로는 존재하지 않는다)
get, set안의 변수는 _를 붙여 새로 네이밍 해주어야한다.
** `_`로 시작하는 프로퍼티는 private 또는 내부적인 속성이라는 뜻으로,
이런 프로퍼티는 외부에서 직접 접근이 가능하기는 하지만 객체 내부에서만 활용하고, 외부에서는 건드리지 않는 것이 관습이다
(위의 코드에서 age(실제 값)는 _age(별도의 프로퍼티)에 저장되고, 프로퍼티에 접근하는 것은 getter와 setter를 통해 이뤄진다.)
** 자바스크립트의 객체의 프로퍼티는 크게 두 종류로 나뉠 수 있다.
1) 데이터 프로퍼티(data property, 일반적인 프로퍼티)
: 객체 내부에 저장된 실제 데이터 값, 설명자 value와 writable
네가지 `어트리뷰트` (attribute, 객체의 프로퍼티를 정의하고 제어하는 내부 속성)가 존재한다
[[Value]]: 프로퍼티의 값입니다.
[[Writable]]: 프로퍼티의 값을 변경할 수 있는지 여부를 나타냅니다.
[[Enumerable]]: 프로퍼티가 for...in 루프나 Object.keys() 메서드 등을 통해 열거 가능한지 여부를 나타냅니다.
[[Configurable]]: 프로퍼티의 삭제, 속성 변경 여부를 나타냅니다.
2) 접근자 프로퍼티(accessor property)
:설명자 value와 writable가 없는 대신에 ( = 키(key)와 값(value)을 가지지 않고 ) get과 set이라는 함수를 가진다.
[[Get]]: 인수가 없는 함수로, 프로퍼티를 읽을 때 호출되는 getter 함수입니다.
[[Set]]: 인수가 하나인 함수로, 프로퍼티에 값을 할당할 때 호출되는 setter 함수입니다.
[[Enumerable]]: 데이터 프로퍼티와 동일하게 프로퍼티가 열거 가능한지 여부를 나타냅니다.
[[Configurable]]: 데이터 프로퍼티와 동일하게 프로퍼티의 속성 변경 가능 여부를 나타냅니다.
즉, 자바스크립트 객체 속성에 접근하듯이 접근자 프로퍼티를 호출하면, 함수 호출 문법이 아니더라도 getter & setter 함수가 호출되는 것과 같은 것이다. 한마디로 Getter와 Setter 함수 자체가 접근자 프로퍼티이라고 보면 된다.
정리하자면 `데이터 프로퍼티`는 값 자체를 다루고,
`접근자 프로퍼티`는 값이 없지만 대신 get과 set을 통해 값에 접근하거나 설정할 때 로직을 추가할 수 있다.
프로퍼티는 접근자 프로퍼티(get/set 메서드를 가짐)나 데이터 프로퍼티(value를 가짐) 중 한 종류에만 속하고 둘 다에 속할 수 없다는 점을 항상 유의해야한다. (어트리뷰트를 섞어서 쓸 수 없다. 예를 들어, 한 프로퍼티에 get과 value를 동시에 설정하면 에러가 발생한다)
3. 키워드 super :: 클래스를 통해 확장하기
class Shape{
constructor(width, height){
this.width = width;
this.height = height;
}
draw() {
console.log("그리기")
}
getArea() {
return this.width * this.height;
}
}
class Triangle extends Shape {
draw() {
super.draw(); // super 키워드로 상위 메소드 가져오기
console.log('🔺')
}
getArea() {
this.width * this.height / 2 // 메소드 재정의
}
}
4. 정적(static)변수 & 메서드
`인스턴스`(클래스로 인해 만들어진 객체)가 아니라 `클래스` 자체에 붙게되는 속성으로, 클래스명으로 static 키워드를 사용하여 직접 참조가 가능하다.
1) 클래스 단위로 관리되어야하는 변수나 함수가 필요할 때 사용한다.
( http 요청을 보내는 작업들만 모아둔 클래스일 때 공용 헤더를 보관하거나,
클래스 메서드에서 공통으로 사용할 에러 핸들링 or 로깅 함수를 선언 시 )
2) 상태정보가 필요없는 유사한 성질의 유틸성함수들을 클래스로 묶고 싶을 때 사용한다.
참고
https://inpa.tistory.com/entry/JS-📚-getter-setter-란
https://ko.javascript.info/property-accessors
'JavaScript' 카테고리의 다른 글
[Javascript] 파라미터? 인자? 헷갈리는 용어 정리와 argument 객체, 나머지 매개변수에 대해 알아보기 (0) | 2024.03.09 |
---|---|
웹브라우저에서의 저장소에 대해 알아보기 (로컬스토리지, 세션 저장소, IndexedDB) (0) | 2024.03.08 |
[javascript] 리터럴과 타입에 대해 정리하기 (0) | 2024.03.07 |
자바스크립트 인증에 대해서 (0) | 2024.02.20 |
JavaScript의 동작원리에 대해 (0) | 2024.01.12 |