엘리님 class강의를 듣고 정리한 내용입니다.
// 클래스 선언
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
speak(){
console.log(`${this.name}: hello!`);
}
// 민주 만들기
const minju = new Person('minju', 20);
minju.speak();
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// 값을 리턴하고
get age(){
return this._age;
}
// 값을 설정할 수 있다. 어떤 값을 설정할 것인가? 알아야 하기 때문에 value를 받아와야 한다.
set age(value){
this._age = value < 0 ? 0 : value; // 0보다 작은 숫자를 넣었으면 0를 보내줘라~
}
}
// 그런데, 말도 안되는 값을 넣으면 어떡하지? 나이가 -1 살이 될 수 있나?
// 사용자가 잘못 사용해도 방어해 줄 수 있는 것이 게터와 세터!
const user1 = new User('Steve', 'Jobs', -1);
💡getter와 setter가 어떻게 동작하는 방법!
우리가 getter를 정의하게 되면, this.age
가 메모리에 저장된 값을 읽어오는게 아니라, get age()
라는 함수를 실행하게 된다.
그리고 우리가 setter를 정의하는 순간, 값을 할당할 때 =age
로 받아온 값을 바로 할당하는 것이 아니라, setter를 실행하게 된다. 그런데, this.age = value라고 되어 있으니, 또 다시 그 함수를 호출하게 되고, 또 호출하게 되고, 그렇게 콜 스택 사이즈 초과 에러가 나오게 된다.
➡️ 이를 방지하기 위해, getter와 setter안의 변수를 조금 다른 걸로 만들어줘야 한다. 보통 변수 앞에 _ underscore을 달아 표현한다. _age
class를 만들때 constructor를 사용하지 않고 만드는 방식인데, too soon! 아직 여러 브라우저들에서 지원이 되지 않는다.
// constructor 없이 class를 만든다.
// publicfield는 class 밖에서도
class Experiment {
publicField = 2;
#privateField = 0;
}
const experiment = new Experiment();
console.log(experiment.publicField); // 2
console.log(experiment.privateField); // undefined
간혹 생기는 오브젝트에 상관없이 동일하게 반복적으로 가지고 있는 프로퍼티와 메소드가 있을 수 있다. 그럴 때, 앞에 static을 붙여줘서, 그 프로퍼티/메소드는 클래스에 붙어있게 만들 수 있다.
class Article {
static publisher = 'Dream coding';
constructor(articleNumber) {
this.articleNumber = articleNumber;
}
static publisher() {
console.log(Article.publisher); // 이 부분에서 this대신 class명 사용한 걸 주목!
}
}
const article1 = new Article(1);
console.log(article1.publisher); // undefined값이 나온다.
console.log(Article.publisher); // 'Dream coding'이 정상적으로 출력된다.
내가 직사각형, 삼각형, 원을 만들수 있는 클래스를 만든다고 할 때, 어떻게 만드는게 가장 효율적일까?
넓이 높이 등을 공통적으로 가지고 있기 때문에, Shape을 공통적으로 만들어서 이 도형들을 만들어주면 된다!
다른 클래스의 속성을 extends로 받아왔다! 그런데 메소드 하나만 조금 변경하고 싶다면?
그 부분을 overriding 해주면 된다!
class Shape {
constructor(width, height, color){
this.width = width;
this.height = height;
this.color = color;
}
draw(){
console.log(`drawing ${this.color} color of`);
}
getArea(){
return this.width * this.height;
}
}
class Rectagle extends Shape{} // Shape의 속성들을 그대로 상속해온다.
const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
// drawing blue color of 가 출력된다.
/* 다양성 */
// 삼각형의 경우에는 넓이 구하는 공식이 다르다. 이 때는 어떻게? 그 부분만 재정의 overriding 해주기!
class Triangle extends Shape{
getArea(){
return (this.width * this.height) / 2;
}
// 공통적으로 가지고 있는 그리는 메소드도 사용하고 싶고, 추가로 새로운 기능도 해주고 싶다!
draw(){
super.draw(); // 'super'라는 키워드를 사용해주면 된다!
console.log(◮) // 그리고 수정원하는 곳은 overriding해주면 된다.
}
}
const triangle = new Triangle(20, 20, 'red');c
console.log(triangle);// 기존 draw와 새로 작성한 삼각형이 모두 출력된다.ㄱ
다음으로는 https://ko.javascript.info/class 를 보며 추가로 작성해보며 클래스에 대해 완전 정복 해보자!
기본문법
class MyClass{
// 여러 메서드를 정의할 수 있음
constructor(){...}
method1() {...}
method2() {...}
}
// 예시 : 클래스 만들기
class User{
constructor(name){
this.name = name;
}
sayHi() {
console.log(`Hi, ${this.name});
}
}
// 예시 : 클래스로 오브젝트 만들기
const minju = new User(minju);
minju.sayHi();
// Hi, minju!
클래스를 만들 때는 메서드 사이에 쉼표를 넣지 않아야 한다!!
2 . 클래스란
클래스는 새로운 개체가 아니라 함수의 한 종류이다!
```jsx
class User{
constructor(name){this.name = name;}
sayHi() {alert(this.name)}
}
// User가 함수라는 증거
alert(typeof User); //function
```
1) `User`라는 이름을 가진 함수를 만드는데, 본문은 생성자 메서드 `constructor`에서 가져온다. 생성자 메서드가 없으면 본문이 비어있는 함수가 만들어진다.
2) `sayHi`같은 클래스 내에서 정의한 메서드를 `User.prototype`에 저장한다.
3) `new User`를 호출해 객체를 만들고, 객체의 메서드를 호출하면 메서드를 prototype 프로퍼티를 통해 가져온다. 그렇기에 객체에서 클래스의 메서드를 접근할 수 있는 것이다.
클래스는 단순한 편의 문법(syntactic sugar : 기능은 동일하나 기존 문법을 쉽게 읽을 수 있게 만든 문법)이 아니다.
물론 순수 함수 작성식으로 클래스의 역할을 하는 함수를 작성할 수가 있다. 그러나! class
로 만든 함수엔 특수 내부 프로퍼티인 [[IsClassConstructor]]:true
가 이름처럼 따라붙고 이를 다양한 경우에 활용한다.` 이에 대해서는 추후 경험하게 될 것.
클래스 표현식
함수처럼 클래스도 다른 표현식 내부에서 정의, 전달, 반환, 할당할 수 있다.
4-1. 클래스 표현식 만들기 → 클래스에 이름 안 넣어줌
let User = class {
sayHi() {
alert("안녕하세요.")
}
};
new User().sayHi(); // 새로운 유저를 만들고, (함수실행시켜줘야 하기 때문에 괄호 넣어줌)
// sayHi()메서드를 실행해라.
4-2. 기명 함수 표현식 (Named Function Expression) → 클래스에 이름 넣어줌
let User = class MyClass {
sayHi() {
alert(MyClass); // MyClass는 오직 클래스 안에서만 사용 가능
}
};
new User().sayHi();
4-3. 필요에 따라 동적으로 클래스 생성
// 클래스를 선언하고 반환하는 함수를 선언
function makeClass(phrase){
return class{
sayHi(){
alert(phrase);
};
};
}
// 새로운 클래스 만들기
const User = makeClass("안녕하세요");
new User().sayHi(); // 안녕하세요.
getter와 setter
getter와 setter는 User.prototype
에 정의된다.
class User{
constructor(name){
this.name = name;
}
get name(){
return this._name;
}
set name(value){
if(value.length < 4){
alert("이름이 너무 짧습니다.");
return;
}
this._name = value;
}
}
const minju = new User("minju");
console.log(minju.name);
계산된 메서드 이름 [...]
class User {
['say'+'Hi'](){
alert("Hello");
}
}
const minju = new User();
console.log(minju.sayHi());
클래스 필드
엘리님이 알려주신 대로 프로퍼티 이름 = 값을 써주면 간단히 클래스 필드를 만들 수 있다.