JavaScript/드림코딩 엘리 - 자바스크립트 기초 강의 (ES5+)

드림코딩 엘리 - 자바스크립트 기초 강의(ES5+) (6편)

정ㅇr 2021. 11. 11. 22:27
728x90

간단한 개념 정리

 

클래스 : 연관된 속성(fields), 메소드(methods)가 포함된 것을 말함

간혹 메소드가 없이 데이터만 들어 있는 클래스도 존재하는데 이를 데이터 클래스라고 말한다.

 

클래스의 내부적으로 보여주는 변수, 밖에서 보이는 변수를 구분 짓는 것을 '캡슐화(encapsulation)'라고 한다.

클래스를 이용해서 상속, 다형성이 일어날 수 있음.

이런 모든 것들을 말해서 객체지향이라고 한다.

 

클래스 (= 템플릿)
- 한번만 선언할 수 있음

- 어떤 종류의 데이터만 들어올 수 있다라는 틀만 정의해 놓는다고 볼 수 있음

ex) 붕어빵 틀

 

오브젝트

- 클래스를 이용해서 새로운 인스턴스를 생성하면 오브젝트가 된다

- 오브젝트는 클래스를 이용해서 많이 만들 수 있다

- 클래스는 틀만 정의해놓은 것이라서 메모리에 올라가지 않지만, 오브젝트는 실제 데이터도 포함하기 때문에 메모리에 올라가게 된다

ex) 팥붕어빵, 슈크림붕어빵, 피자붕어빵


1. 클래스

'use strict';
// Object-oriented programming
// class: template
// object: instance of a class
// JavaScript classes
//  - introduced in ES6 (JS 클래스 도입은 ES6부터 되었다.)
//  - syntactical sugar over prototype-based inhritance

// 1. Class declarations
class Person {
    // constructor (생성자)
    constructor(name, age) {
        // fields
        this.name = name;
        this.age =  age;
    }

    // methods (메소드)
    speak() {
        console.log(`${this.name}: hello!`);
    }
}

// object 생성
const ellie = new Person('ellie', 20);
console.log(ellie.name);
console.log(ellie.age);
ellie.speak();

 

2. Getter and Setter

관련 개념에 대해서 간단한 예시

커피 자판기 = 클래스 (class)

자판기의 커피 개수, 동전 .. = 속성 (properties)

동전을 넣는다, 커피를 꺼낸다 .. = 메소드 (methods)

 

여기서 커피 개수(속성)를 int로 본다면 사용자가 -1을 입력했을 때, 이를 사용하면 안되는 경우가 발생한다.

이를 방지하기 위해서 getter, setter를 사용한다고 볼 수 있다.

커피 개수(속성)는 최소가 0이기 때문에 사용자가 -1을 입력하더라도 0으로 바꿔주기 위해 setter를 사용한다.

 

커피 개수(속성)를 누구나 마음대로 설정할 수 있으면 안되기 때문에 getter, setter는 private으로 하는 것이고,

이러한 과정을 통틀어서 encapsulation(캡슐화)라고 한다.

 

강의를 들으면서 이 예시를 듣고 이렇게나 쉽게 설명을 할 수 있구나 싶어서 감탄했다.

 

// 2. Getter and Setter
class User {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    get age() {
        return this.age;
    }

    set age(value) {
        this.age = value;
    }
}

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

위의 코드를 작성해서 실행해보면 다음과 같이 call stack 관련 에러가 발생한다.

그 이유는

getter, setter를 생성하고 User 클래스의 인스턴스를 만들어서 생성자를 호출하게 되면,

this.age 는 메모리에 저장된 값을 불러오는 것이 아니라 getter 메소드를 호출하고,

= age 부분은 메모리에 값을 할당하는 것이 아니라 setter 함수를 호출한다.

 

여기서 setter 안에서 전달된 값은 this.age에 할당하는 것이 아니라, 계속해서 setter를 호출을 반복하기 때문에

Maximum call stack seze exceeded 라는 에러가 발생하는 것이다.

그러므로 getter와 setter 안에 들어가는 리턴값은 생성자에 들어가는 값과 조금 다르게 설정해야 한다.

class User {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    get age() {
        return this._age;
    }

    set age(value) {
        // if (value < 0) {
        //     throw Error('age cannot be negative!');
        // } 이처럼 에러 문구를 띄울 수도 있다.
        this._age = value < 0 ? 0 : value;
    }
}

 

3. Fields (public, private)

// 3. Fields (public, private)
class Experiment {
    publicField = 2;
    #privateField = 0; // 클래스 밖에서는 값을 읽을 수도 변경할 수도 없음
}
const experiment = new Experiment();
console.log(experiment.publicField);
console.log(experiment.privateField); // undefined

 

4. Static properties and methods

클래스 안에 있는 fields, methods는 object를 생성할 때마다 그대로 복사된다. 다만 그 안의 값들은 변경될 수 있다.

간혹 object에 상관없이 클래스 자체에 연결해서 값이나 메소드를 사용하고 싶을 때 static을 사용한다.

object에 상관없이 클래스에 static으로 속성이나 메소드를 정의해서 공통적으로 사용하는 것은 메모리 사용량을 줄일 수 있다.

// 4. Static properties and methods
class Article {
    static publisher = 'Dream Coding';
    constructor(articleNumber) {
        this.articleNumber = articleNumber;
    }

    static printPublisher() {
        console.log(Article.publisher);
    }
}

const article1 = new Article(1);
const article2 = new Article(2);

// static 속성이나 메소드를 호출할 때는 클래스 이름을 사용해서 호출한다.
console.log(Article.publisher);
Article.printPublisher;

 

5. Inheritance (상속과 다형성)

// 상속, 다형성
// Inheritance
class Shape {
    constructor(width, height, color) {
        this.width = width;
        this.height = height;
        this.color = color;
    }

    draw() {
        console.log(`drawing ${this.color} color!`);
    }

    getArea() {
        return this.width * this.height;
    }
}

// extends를 이용해서 상속받아서 부모클래스의 생성자, 메소드들을
// 사용할 수 있게 된다.
class Rectangle extends Shape {}

class Triangle extends Shape {
    // 부모클래스의 메소드를 재정의하면서,
    // 원래 메소드의 내용도 실행하고 싶으면
    // super.메소드명()을 사용하면 된다.
    draw() {
        super.draw();
        console.log('삼각형');
    }
    // 다음과 같이 부모클래스의 메소드를 재정의해서 사용할 수도 있다.
    getArea() {
        return (this.width * this.height) / 2;
    }
}

const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
console.log(rectangle.getArea());
const triangle = new Triangle(20, 20, 'red');
triangle.draw();
console.log(triangle.getArea());

 

6. Class checking: instanceOf -> return true / false 

// 6. Class checking: instanceOf, true/false return
console.log(rectangle instanceof Rectangle);
console.log(triangle instanceof Rectangle);
console.log(triangle instanceof Triangle);
console.log(triangle instanceof Shape);
// 모든 object는 자바스크립트의 Object를 상속 받은거라고 볼 수 있다.
console.log(triangle instanceof Object);

 

참고

https://www.youtube.com/watch?v=_DLhUBWsRtw&lc=UgwEzuVD1kadq6lrtzZ4AaABAg&ab_channel=%EB%93%9C%EB%A6%BC%EC%BD%94%EB%94%A9by%EC%97%98%EB%A6%AC

반응형