Class: 제로베이스
Created: December 21, 2022 9:09 AM
Type: Javascript
강의 명: 초심자도 빈틈없이 학습하는 자바스크립트
연관 있는 데이터들을 한군데 모아 놓는 컨테이너 같은 역할을 한다. 그전에는 클래스를 정의하지 않고 객체를 정의해서 사용하는 방법이 있었고 객체를 만들때 함수를 이용해서 템플릿(클래스 같은 역할)을 만드는 방법이 있었다.
// 생성자
function Person({name, age}) {
this.name = name;
this.age = age;
}
Person.prototype.introduce = function() {
return `안녕하세요, 제 이름은 ${this.name}입니다.`;
};
const person = new Person({name: 'Kody', age: 25});
console.log(person.introduce()); // 안녕하세요, 제 이름은 Kody입니다.
// 클래스
class Person {
// 이전에서 사용하던 생성자 함수는 클래스 안에 `constructor`라는 이름으로 정의.
constructor({name, age}) { //생성자
this.name = name;
this.age = age;
}
// 객체에서 메소드를 정의할 때 사용하던 문법을 그대로 사용하면,
// 메소드가 자동으로 `Person.prototype`에 저장.
introduce() {
return `안녕하세요, 제 이름은 ${this.name}입니다.`;
}
}
const person = new Person({name: 'Kody', age: 25});
console.log(person.introduce()); // 안녕하세요, 제 이름은 Kody입니다.
https://www.youtube.com/watch?v=_DLhUBWsRtw
연관있는 데이터들을 묶어놓은 컨테이너같은 역할
fields(속성)와 methods(행동)로 이루어져있다. 간혹 메소드는 없이 속성들로만 이루어진 클래스도 있는데 그런 클래스를 데이터 클래스라고 부른다.
클래스 자체에는 데이터가 들어있지 않고, 템플릿만이 정의된다.
어떤 데이터가 들어올 수 있는지 정의해두고, 한번만 선언한다.
그 클래스를 이용해서 실제 데이터를 넣어서 만드는 것이 객체(Object)다.
객체는 클래스를 이용해서 쉽게 만들 수 있고, 클래스는 정의만한 것이기 때문에 실제 메모리에 올라가지는 않지만, 객체는 메모리에 올라간다.
앞에서 공부한 내용과 동일
자판기 커피머신을 예로 들어보자.
자판기 커피머신이라는 클래스가 있다. 우리는 자판기 커피에서 커피를 몇잔 마실지 설정할 수 있고(속성), 동전을 넣고, 커피를 내려 마실 수 있다(메소드).
우리가 자판기를 이용할 때 커피의 잔 수는 마이너스가 될 수 없다.
⇒ 때문에 getter와 setter를 사용해야 한다. 사용자가 멍청하게 커피 개수를 -1로 설정하면 안되니까. 설령 그렇게 하더라도, 우리는 setter를 이용해 0으로 만들어 주는것.
⇒ 근데 다른 사람이 커피 개수를 설정하는게 좋을까 안좋을까? 당연히 다른사람이 자판기 커피 개수를 수정하는건 원치 않는다. 때문에, number of coffee라는 속성을 private으로 만드는 것. 이게 바로 incapsulation이다.
예제 코드를 보자
class User {
constructor(first, last, age) {
this.firstName = first;
this.lastName = last;
this.age = age;
}
}
const user1 = new User('Kody', 'Kim', -1);
console.log(user1.age) // -1
나이를 위와같이 사용자가 -1로 설정하게 되면, 당연히 -1로 지정되는 것이 당연.
하지만 나이가 -1은 말이 인되기 때문에, 조금더 우리가 방어적인 자세로 만들어주는 것이 getter와 setter의 역할.
get이라는 키워드를 통해 값을 return 하고, set 키워드를 통해 값을 설정할 수 있다.
class User {
constructor(firstName, lastNamem, age) {
this.firstName = firstNamem;
this.lastName = lastNamem;
this.age = age;
}
get age() {
return this._age;
}
set age(value) {
// 잘못된 값 할당 적극적으로 막기 (에러 던저주기)
// if (value < 0) {
// throw Error(`age can not be negative`);
// }
// 잘못된 값 할당 젠틀하게 막기 (0으로 저장하기)
this._age = value < 0 ? 0 : value;
}
}
const user1 = new User('Kody', 'Kim', -1);
console.log(user1.age) // 0
이 때 getter와 setter 안에서 사용되는 프로퍼티 이름앞에 관습적으로 언더바를 작성해준다. this.age
를 호출하면 get age() {}
가 호출되어 지는데 안에서 또 this.age
를 사용하면 다시 `get age() {}
가 호출되어 무한루프에 빠지기 때문이다. 이 때 get age() {}
안에서는 this._age
같은 형태로 작성하면 무한루프를 방지할 수 있다.
마찬가지로 this.age = value
와 같이 값을 할당할 때 set age() {}
가 호출되어 지는데 안에서 또 다시 this.age = value
와 같이 사용하면 또다시 set age() {}
가 호출되어 무한루프에 빠지기 때문이다. 이 때 set age() {}
안에서는 this._age = value
같은 형태로 작성하면 무한루프를 방지할 수 있다.
constructor는 인스턴스를 생성하고 클래스 필드를 초기화하기 위한 특수한 메서드이다.
constructor는 클래스 안에 한 개만 존재할 수 있다. 2개 이상 있을 경우 Syntax Error가 발생하니까 주의하자.
class Person {
height = 180; // 인스턴스 변수
// constructor는 이름을 바꿀 수 없다.
constructor(name, age) {
// this는 클래스가 생성할 인스턴스를 가리킨다.
this.name = name;
this.age = age;
}
write() {
return `이름은 ${this.name}, 나이는 ${this.age} 입니다.`;
}
}
let person1 = new Person('john', 23);
console.log(person1.name); // john
console.log(person1.age); // 23
console.log(person1.height); // 180
클래스의 메소드 정의할 떄는 객체 리터럴에서 사용하던 문법과 유사한 문법 사용
class Calculator {
add(x, y) {
return x + y;
}
subtract(x, y) {
return x - y;
}
}
let calc = new Calculator();
calc.add(1,10); // 11
객체 리터럴의 문법과 마찬가지로, 임의의 표현식을 대괄호로 둘러싸서 메소드의 이름
으로 사용할 수도 있다.
const methodName = 'introduce';
class Person {
constructor({name, age}) {
this.name = name;
this.age = age;
}
[methodName]() { // 메소드의 이름은 `introduce`가 된다.
return `안녕하세요, 제 이름은 ${this.name}입니다.`;
}
}
console.log(new Person({name: 'Kody', age: 25}).introduce());
// 안녕하세요, 제 이름은 Kody입니다.
Getter - 프로퍼티 값을 가져오기 위한 함수
Setter - 프로퍼티 값을 설정하기 위한 함수
class Info {
constructor({name, age}) {
this.name = name;
this.age = age;
}
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
write() {
return `이름은 ${this.name}, 나이는 ${this.age} 살`
}
}
let info = new Info({name: 'kody', age: 25})
console.log(info.name); // kody
info.name = 'james'
console.log(info.name) // james
class Info {
#privateValue = "Kody"
publicValue = "50kg";
}
let info = new Info();
console.log(info.privateValue); // undefined
console.log(info.publicValue); // 50kg