※ 함수와 클래스 비교
함수 - 특정 기능을 하는 변수와 구문으로 이루어져 있다.
기능 단위의 코드 그룹화, 기능 단위의 중복 코드 제거 및 코드 재사용
클래스 - 연관 있는 변수와 함수로 구성되어 있다.
객체 단위의 코드 그룹화, 객체 단위의 중복 코드 제거 및 코드 재사용
※ 객체 단위의 코드 그룹화?
- 위에서 클래스는 연관 있는 변수와 함수로 구성되어 있다고 했다.
- 이런식으로 객체 단위로 함수와 변수를 구분해서 코드를 작성하면 필요한 함수들이 찾기 편해지고 객체단위의 코드 재사용 및 중복코드를 제거할 수 있다.
※ 클래스 관련 기본 개념 및 용어정리
- 인스턴스 - 객체를 의미한다. ex) 붕어빵 틀 = 클래스 , 붕어빵 = 인스턴스(또는 객체)
- 프로퍼티 - 클래스 내부에 만드는(포장하는) 변수를 의미, 멤버변수라고도 한다.
객체 내부에서 사용하는 정보, 객체 내부 함수(메서드)에서 처리한 결과값 저장
- 메서드 - 클래스에 만드는(포장하는) 함수를 의미, 멤버함수라고도 한다.
주로 객체 프로퍼티 값 변경 및 탐색, 클래스 대표 기능등이 담기게 된다.
- 생성자 - 인스턴스가 만들어지면서 자동으로 호출되는 함수
주 용도는 프로퍼티 초기화 역할
출처: https://debugdaldal.tistory.com/144 [달달한 디버깅]
*일을 하는 일꾼의 틀 (Class)을 만들어 놓고,
일꾼들에게 일을 주면서 생성해서 (클래스의 생성자를 이용해서 오브젝트를 만듬)
여러 일꾼들에게 일을 시킬 수 있다. 이때 일을 하는 로직들은 다 Class에 정의되어져 있으니 코드를 계속 재사용 할 수 있다*
- static
static 키워드는 클래스 레벨의 메서드를 정의함.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes/static
static - JavaScript | MDN
static 키워드는 클래스의 정적 메서드를 정의합니다.
developer.mozilla.org
// static 정적 프로퍼티, 메서드
class Fruit {
static MAX_FRUITS = 4;
// 생성자: new 키워드로 객체를 생성할때 호출되는 함수
constructor(name, emoji) {
this.name = name;
this.emoji = emoji;
}
// 클래스 레벨의 메서드
static makeRandomFruit() {
// 클래스 레벨의 메서드에서는 this를 참조할 수 없음
return new Fruit('banana', '🍌');
}
// 인스턴스 레벨의 메서드
display = () => {
console.log(`${this.name}: ${this.emoji}`);
};
}
const banana = Fruit.makeRandomFruit();
console.log(banana);
console.log(Fruit.MAX_FRUITS);
// apple은 Fruit 클래스의 인스턴스이다.
const apple = new Fruit('apple', '🍎');
// orange은 Fruit 클래스의 인스턴스이다.
const orange = new Fruit('orange', '🍊');
console.log(apple);
console.log(orange);
console.log(apple.name);
console.log(apple.emoji);
apple.display();
Math.pow();
Number.isFinite(1);
- field - class 내부에 있는 property #(캡슐화)
// 접근제어자 - 캡슐화 (외부에서 수정/접근/호출 할 수 없도록 클래스 내부에서만 사용가능)
// private(#), public(기본), protected
class Fruit {
#name;
#emoji;
#type = '과일';
constructor(name, emoji) {
this.#name = name;
this.#emoji = emoji;
}
#display = () => {
console.log(`${this.#name}: ${this.#emoji}`);
};
}
const apple = new Fruit('apple', '🍎');
//apple.#name = '오렌지'; // #field는 외부에서 접근이 불가능함
console.log(apple);
- getter, setter (함수)
접근제어자 get
// 접근자 프로퍼티 (Accessor Property)
class Student {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
fullName() {
return `${this.lastName} ${this.firstName}`;
}
}
const student = new Student('수지', '김');
console.log(student.firstName); //->수지
console.log(student.fullName()); //->함수로 호출할수 있음.! 김 수지
//그러나 원하는건 일반속성에 접근하는 것처럼 하고싶다~ 아래 보십쇼.
//
class Student {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
//접근자프로퍼티를 사용하면,일반속성에 접근하듯 호출해도 함수로 수행함
return `${this.lastName} ${this.firstName}`;
}
set fullName(value) {
console.log('set', value);
}
}
const student = new Student('수지', '김');
console.log(student.firstName);
console.log(student.fullName); //->속성에 접근하듯 만들수 있음.
student.fullName = '김철수'; //할당하면 set이 호출됨.
- 상속과 super키워드
// class Tiger {
// constructor(color) {
// this.color = color;
// }
// eat() {
// console.log('먹자!');
// }
// sleep() {
// console.log('잔다');
// }
// }
// class Dog {
// constructor(color) {
// this.color = color;
// }
// eat() {
// console.log('먹자!');
// }
// sleep() {
// console.log('잔다');
// }
// play() {
// console.log('놀자아~!');
// }
// }
class Animal {
constructor(color) {
this.color = color;
}
eat() {
console.log('먹자!');
}
sleep() {
console.log('잔다');
}
}
class Tiger extends Animal {}
const tiger = new Tiger('노랑이');
console.log(tiger);
tiger.sleep();
tiger.eat();
class Dog extends Animal {
constructor(color, ownerName) {
super(color); //super은 내가 상속하고있는 부모 생성자를 지목.
this.ownerName = ownerName;
}
play() {
console.log('놀자아~!');
}
// 오버라이딩 overriding - 자식 class에서 부모의 class에 있는 함수를 덮어 씌운다.
eat() {
super.eat(); // 부모class의 eat함수를 상속받으면서도
console.log('강아지가 먹는다!'); //내가 필요한 기능을 구현한다.
}
}
const dog = new Dog('빨강이', '엘리');
console.log(dog);
dog.sleep();
dog.eat();
dog.play();
quiz1) <캡슐화/정보은닉>
// 카운터를 만들기
// 0 이상의 값으로 초기화 한 뒤 하나씩 숫자를 증가할 수 있는 카운터를 만들기
// Counter 클래스 만들기
//카운터라는 클래스는 인크레먼트 함수를이용해 값을 하나씩 증가하고
//벨류라는 속성을 통해 사용자가 값을 확인할수 있게!
// const counter = new counter(0);
// counter.increment(); //1
// counter.increment(); //2
// console.log(count.value);
class counter {
#value; //내부 private field
constructor(startValue) {
//클래스 내부에 instance를 생성할때는 외부에서 초깃값을 전달받는데,
if (isNaN(startValue) || startValue < 0) {
//이 초깃값이 숫자가 아니거나 영보다 작다면
this.#value = 0; //0으로 초기화
} else {
this.#value = startValue; //그외에는 숫자이기때문에 그 숫자부터 카운터가 될 수 있도록
}
}
//외부에서 벨류를 볼수만 있기때문에 접근 제어자 이용
get value() {
return this.#value; //getter를 사용하여 현재 값을 읽기만 가능,벨류값에 접근하면 내부에있는 벨류를 리턴
}
increment = () => { //외부에서 조작 불가, 내부의 increment()함수로 숫자를 증가시키고 그걸 읽을수만있음
this.#value++;
};
}
quiz2) <클래스/상속>
// 정직원과 파트타임직원을 나타낼 수 있는 클래스를 만들어 보자
// 직원들의 정보: 이름, 부서이름, 한달 근무 시간
// 매달 직원들의 정보를 이용해서 한달 월급을 계산할 수 있다
// 정직원은 시간당 10000원
// 파트타임 직원은 시간당 8000원
// 정직원과 파트타임직원을 나타낼 수 있는 클래스를 만들어 보자
// 직원들의 정보: 이름, 부서이름, 한달 근무 시간
// 매달 직원들의 정보를 이용해서 한달 월급을 계산할 수 있다
// 정직원은 시간당 10000원
// 파트타임 직원은 시간당 8000원
const ellie = new FullTimeEmployee('엘리', 's/w', 30);
const bob = new PartTimeEmployee('밥', 's/w', 20);
console.log(ellie.calculatePay());
console.log(bob.calculatePay());
class Employee {
constructor(name, department, hoursPerMonth, payRate) {
this.name = name;
this.department = department;
this.hoursPerMonth = hoursPerMonth;
this.payRate = payRate;
}
calculatePay() {
return this.hoursPerMonth * this.payRate;
}
}
//
class FullTimeEmployee extends Employee { //-> extends 부모클래스 상속
constructor(name, department, hoursPerMonth) {//-> 외부로부터 받아오는 정보
super(name, department, hoursPerMonth, 10000);
}
}
class PartTimeEmployee extends Employee {
constructor(name, department, hoursPerMonth) {
super(name, department, hoursPerMonth, 8000);
}
}
//
//
class FullTimeEmployee extends Employee {
//-> extends 부모클래스 상속
static #PAY_RATE = 10000; // 클래스레벨인 PAY_RATE를 지정.숫자를 직접쓰기보다는 이렇게!
constructor(name, department, hoursPerMonth) {
//-> 외부로부터 받아오는 정보
super(name, department, hoursPerMonth, FullTimeEmployee.PAY_RATE);
}
}
class PartTimeEmployee extends Employee {
static #PAY_RATE = 8000; //->외부에서 금액은 접근 불가하게
constructor(name, department, hoursPerMonth) {
super(name, department, hoursPerMonth, PartTimeEmployee.PAY_RATE);
}
}
//