본문 바로가기

JS

JS - class

JS 강의 필기 + 추가

object-oriented programming

class: template 개념. fields(속성)과 method(행동)으로 이루어짐

object: an instance of a class

constructor: 생성자. 이를 통해서 object를 만들 때 필요한 데이터를 전달

class Person {
    constructor(name, age) {
        // fields
        this.name = name;
        this.age = age;
    }

    speak() { // method
        console.log(`${this.name}: hello!`);
    }
}

const phin = new Person('phin', 30); // object 생성
console.log(phin.name);
consoole.log(phin.age);
phin.speak();

getter and setter

getter를 정의하면 constructor 안에 있는 this.age는 데이터를 읽어오는 게 아니라 getter를 호출한다.

setter를 정의하면 constructor 안에 있는 = age 는 메모리에 있는 값을 바로 할당하는 게 아니라 setter를 호출한다.

class User {
    // field 3가지: firstName, lastName, _age
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    get age() {
        return this._age; // getter와 setter에 이런 식으로 이름을 다르게 줘야 됨
    }

    set age(value) { // 값을 필터링해 넣기
        this._age = value < 0 ? 0 : value; // value가 음수면 0을 쓰고, 아니면 value를 쓰겠다
    }
}

const user1 = new User('Steve', 'Jobs', -1);
console.log(user1.age);

그래서 getter와 setter 안에서는 생성자에 사용한 것과 동일한 변수명을 쓰면 안 된다. recursion을 무한 반복하는 셈이 되기 때문.

class User {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age; // 여기에 쓴 변수명을 getter와 setter에 그대로 쓰면 안 된다.
    }

    get age() {
        return this.age; // 이렇게 쓰면 maximun call stack size exceeded 에러 남.
    }

    set age(value) {
        this.age = value; // 이렇게 쓰면 전달된 value를 메모리에 업데이트하는 게 아니라 setter를 호출하는 것임
    }
}

const user1 = new User('Steve', 'Jobs', -1);
console.log(user1.age);

사용자가 잘못된 값을 넣었을 때 값을 필터링해 넣는 게 아니라 에러 메시지를 띄우고 싶다면

set age(value) {
    if (value < 0) {
        throw Error('age cannot be negative') // Uncaught Error: age cannot be negative 이렇게 출력됨
    }
    this._age = value;
}

Inheritance(상속)

a way for one class to extend another class

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 Rectangle extends Shape {} // 이렇게만 써도 Shape에 있는 모든 fields와 methods를 포함
const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
console.log(rectangle.getArea());

class Rectangle은 Shape를 그대로 상속한 상태다. 아래는 Shape를 상속하고 일부 바꾸기도 하는, overriding한 class Triangle이다.

class Triangle extends Shape {
    draw() {
        // super.draw(); // 부모의 draw도 실행
        console.log('▲');
    }
    getArea() {
        return (this.width * this.height) / 2;
    }
    toString() {
        return `Triangle, color: ${this.color}`
    }
}
const triangle = new Triangle(20, 20, 'red');
triangle.draw(); // ▲
console.log(triangle.getArea());

instanceOf: class checking

왼쪽의 object가 오른쪽 class의 instance인지 판별해서 true or false를 return

console.log(rectangle instanceof Rectangle); // true
console.log(triangle instanceof Rectangle); // false
console.log(triangle instanceof Shape); // true
console.log(triangle instanceof Object); // true

모든 class들은 object라는 기본 class를 상속한다. class Triangle에서는 이 object에 있는 toString이라는 method를 overriding해서 원하는 대로 변경했다. overriding하지 않고 그대로 상속받아 사용하면 [object object]로 출력된다.

console.log(triangle.toString()); // Triangle, color: red 출력

super

파생 클래스에서 super() 함수가 먼저 호출되어야 this 키워드를 사용할 수 있음. 그렇지 않으면 Uncaught ReferenceError 발생(Must call super constructor in derived class before accessing 'this' or returning from derived constructor).

class Polygon {
    constructor(height, width) {
        this.name = 'Polygon';
        this.height = height;
        this.width = width;
    }
    sayName() {
        console.log('Hi, I am a ', this.name + '.');
    }
  }
  
  class Square extends Polygon {
    constructor(length) {
        // this.height // Uncaught ReferenceError
        super(length, length);
        this.name = 'Square';
    }
    
    get area() {
        return this.height * this.width;
    }
  
    set area(value) {
        this.area = value;
    }
}

let square = new Square(20);
console.log(square); // Square {name: "Square", height: 20, width: 20}

'JS' 카테고리의 다른 글

JS - array  (0) 2020.12.24
JS - object  (0) 2020.12.23
JS - function  (0) 2020.12.21
JS - operator  (0) 2020.12.21
JS - variable  (0) 2020.12.19