😵 ~23.11.10
0801 | JS ES6 :: 클래스 (클래스 정의, strick mode, 은닉화 ,static과 인스턴스) / 클래스 상속
unikue
2023. 8. 1. 19:50
✅ 클래스 정의 방법
class Exam {
constructor(kor = 100, math = 100, eng = 100) {
this.kor = kor;
this.math = math;
this.eng = eng;
}
total() {
return this.kor + this.math + this.eng;
}
}
let exam1 = new Exam(20, 30);
console.log(exam1.total()); // 50
console.log(exam1.kor) // 20
console.log(exam1.eng) // 100
console.log(typeof Exam) // function
- 자바스크립트는 모듈화 불가
- 타입에 대한 형식을 안전하게 사용할 수 있지 X
✅ strict mode
Strict mode - JavaScript | MDN
Callout: 가끔 엄격하지 않은 기본값을 " 느슨한 모드 (en-US)(sloppy mode)"라고 부르기도 합니다. 공식적인 용어는 아니지만 혹시 모르니 알아두세요.
developer.mozilla.org
- 함수를위한 것
- 클래스는 명시 없이도 strict mode로 처리됨
#️⃣ strict mode JavaScript의 strict mode(엄격 모드)는 ES5부터 도입된 기능으로, 코드를 더 엄격하게 처리하여 일부 오류를 방지하고 안전성을 높이는 모드입니다. strict mode를 사용하면 코드 실행에 대해 몇 가지 제한과 변경 사항이 발생합니다. strict mode를 활성화하는 방법은 다음과 같습니다: 전역 스코프에서 사용: 스크립트 파일의 맨 위에 "use strict"; 또는 'use strict';를 추가합니다. 함수 스코프에서 사용: 함수의 맨 위에 "use strict";를 추가합니다. strict mode의 주요 특징과 동작 방식은 다음과 같습니다: 1. 변수 선언: 변수 선언 시 var, let, const를 사용하지 않으면 에러가 발생합니다. 중복된 변수 선언 시 에러가 발생합니다. 2. 전역 객체: strict mode에서 전역 코드의 this는 undefined가 됩니다. (non-strict mode에서는 전역 객체를 가리킵니다) 3. 예약어 사용 제한: 일부 예약어를 변수 이름으로 사용할 수 없습니다. (eval, arguments, implements, interface, package, private, protected, public, static, yield 등) 4. 함수 매개변수: 함수 내에서 동일한 이름의 매개변수를 사용할 수 없습니다. 5. with 문 사용 금지: with 문은 사용할 수 없습니다. 6. delete 연산자 사용 제한: 객체의 프로퍼티를 삭제할 때, 해당 프로퍼티가 열거 가능해야만 가능합니다. 7. 함수와 this: 함수를 호출할 때 this가 전역 객체로 바인딩되지 않고 undefined로 설정됩니다. (호출하는 객체가 없을 때) 8. strict mode 비활성화: strict mode는 함수별로 적용됩니다. 함수 내부에서 strict mode가 아닌 함수를 호출하면, strict mode가 해제됩니다. strict mode는 프로그램에서 오류를 더 잘 발견하고, 더욱 명시적이고 안전한 코드를 작성할 수 있도록 도와줍니다. 따라서 새로운 코드를 작성할 때는 항상 strict mode를 사용하는 것이 권장됩니다. |
✅ 은닉화
class Exam {
// 내부에서만 쓸 private한 것은 #으로 멤버에 표현해준다
#kor
#math
#eng
constructor(kor = 0, math = 0, eng = 0) {
this.#kor = kor;
this.#math = math;
this.#eng = eng;
}
total() {
return this.#kor + this.#math + this.#eng;
}
}
let exam = new Exam(10, 20, 30);
console.log(exam.kor) // undefined
// console.log(exam.#kor)// 밖에서 접근 불가
console.log(exam.eng) // private처리를 안하면 30이 나오지만 처리하면 undefined
console.log(exam.total()); // 60 public 메서드인 total메서드 자체는 작동된다.
#️⃣ getter/settter 지원
class Exam {
// 내부에서만 쓸 private한 것은 #으로 멤버에 표현해준다
#kor //private
#math
#eng
constructor(kor = 0, math = 0, eng = 0) {
this.#kor = kor;
this.#math = math;
this.#eng = eng;
}
total() {
return this.#kor + this.#math + this.#eng;
}
get kor() { //자바에서의 getKor(). kor부분은 밖에 나타나기 위한 함수 명을 기재해주면 됨
return this.#kor;
}
set kor(value) { //자바에서의 setKor(value)
this.#kor = value;
}
}
let exam = new Exam(10, 20, 30);
console.log(exam.kor) // 10 접근할때는 exam.getkor이 아니라 exam.kor로 접근하면 알아서 get/set을 구분하여 처리해줌
console.log(exam.eng) // undefined
console.log(exam.total()); // 60
#️⃣ 정적 멤버인 static과 static을 초기화하는 공간
class Exam {
// 내부에서만 쓸 private한 것은 #으로 멤버에 표현해준다
#kor
#math
#eng
static count; // static count=10;으로 여기서 해도되지만, 초기화하는 공간을 따로 만들 수도 있다.
static {
Exam.count = 10; // 초기화할때 count=10이 아닌 Exam.count=10으로 클래스명이 따라다녀야 함.
//this.count도 가능하지만 static은 인스턴스가 모두 공유하는 변수이므로 바람직하지않음
}
constructor(kor = 0, math = 0, eng = 0) {
this.#kor = kor;
this.#math = math;
this.#eng = eng;
Exam.count++; // 생성자가 생성될떄마다 하나씩 가지는 정적변수. 인스턴스를 생성할 필요가 없으므로 클래스이름과 함께 기재함
}
total() {
return this.#kor + this.#math + this.#eng;
}
get kor() {
return this.#kor;
}
set kor(value) {
this.#kor = value;
}
get eng() {
return this.#eng;
}
}
let exam1 = new Exam(10, 20, 30);
let exam2 = new Exam(50, 60, 70);
console.log(exam1.kor) // 10
console.log(exam2.eng) // 70
console.log(exam1.total()); // 60
// console.log(count); //class안에 있으므로 strict모드가 되어서 undefined로 자동처리되지않음. count is not defined로 오류발생
console.log(Exam.count); // 12 인스턴스가 두개 생성되면서 두번 더해짐
class Exam {
// 내부에서만 쓸 private한 것은 #으로 멤버에 표현해준다
#kor
#math
#eng
static count;
static {
Exam.count = 100;
}
static getKor() {
return this.kor;
}
}
//-------------------
static getKor(exam1) { //만약 static에서 인스턴스의 속성에 접근하고 싶다면 해당 인스턴스를 전달해줘야 사용가능
return exam1.#kor;
}
console.log(Exam.getKor(exam1)) //10
👉 static은 exam.getKor()로 호출해도 exam을 전달하지 않는다. 인스턴스 함수가 자신의 인스턴스를 가리킬때 this를 사용하므로!
// static 멤버가 private일 때
class Exam {
#kor
#math
#eng
static #count; //staic 멤버도 private으로 만들기
static {
Exam.#count = 100;
}
static set count(value) {
Exam.#count = value;
}
static get count() {
return Exam.#count;
}
constructor(kor = 0, math = 0, eng = 0) {
this.#kor = kor;
this.#math = math;
this.#eng = eng;
Exam.count++; // setter에서 작동함. Exam.#count++로 기재하지 않아도 됨
}
}
console.log(Exam.count); // getter로 작동하므로 Exam.#count로 접근하는게 아님
👉 static 변수를 private으로 만든 경우, 동일하게 getter, setter를 설정해주면 된다. 단지 접근만 Exam으로 함.
#️⃣ static과 인스턴스 메서드 문제 풀이
더보기
class Triple {
static triple(n) {
n = n || 1;
return n * 3;
}
triple(n) {
n = n || 1;
return n * 5;
}
}
class BiggerTriple extends Triple {
static triple(n) {
return super.triple(n) * super.triple(n);
}
}
console.log(Triple.triple()); // 3
console.log(Triple.triple(6)); //18
console.log(BiggerTriple.triple(3)); // 81
var tp = new Triple();
console.log(BiggerTriple.triple(3)); //81
console.log(tp.triple()); //5 -- 인스턴스의 triple메서드이므로 static triple(n)이 작동되는게 아니라 객체의 함수인 triple(n)이 작동된다
console.log(tp.constructor.triple(4)); //12
✅ 클래스 상속
class Exam {
#kor
#math
#eng
static count= 100;
constructor(kor = 0, math = 0, eng = 0) {
this.#kor = kor;
this.#math = math;
this.#eng = eng;
Exam.count++; // 생성자가 생성될떄마다 하나씩 가지는 정적변수. 클래스이름과 함께 기재함
}
total() {
return this.#kor + this.#math + this.#eng;
}
get kor() {
return this.#kor;
}
set kor(value) {
this.#kor = value;
}
}
console.log("상속 ------------------------------------")
class NewlecExam extends Exam {
#com;
constructor(kor, math, eng, com) {
super(kor, math, eng); // 부모의 생성자를 호출 -- 인자가 없으면 super()이지만 여기선 초기화기키고 싶은 애들을 지정
this.#com = com; // 자손이 초기화
}
total() { // 오버라이드
return super.total() + this.#com;
}
}
let exam3 = new NewlecExam(50, 50, 50, 50);
console.log(exam3.total()); // 200
console.log(typeof exam2, typeof Exam, typeof NewlecExam); // true true
console.log(exam1 instanceof Exam, exam3 instanceof Exam) // false true
console.log(exam1 instanceof NewlecExam, exam3 instanceof NewlecExam) // false true
console.log(Object.hasOwn(exam1.__proto__, 'total')) // true entity에 total property가 존재하는가?
console.log(Object.hasOwn(exam3.__proto__, 'total')) // true entity에 total property가 존재하는가?
console.log(Object.hasOwn(exam1, 'total')) // false
👉 exam1은 객체. Object.hasOwn은 개체(Exam)에 해당 property가 정의되었는지를 확인하므로, exam,'total'은 false가 반환된다.