/ JAVASCRIPT

JavaScript(5) - class vs. object

JavaScript 관련 포스팅

Class

  • ES6부터 도입됨
  • 다양한 object를 만들기 위한 청사진, template (일종의 ‘틀’)
  • 관련 있는 변수와 함수를 묶어 놓은 것
  • 속성(field)과 method로 구성됨
  • 한 번만 선언
  • data가 들어있지 않아 메모리에 올라가지 않음
  • 붕어빵 틀로 비유함

      class Person {
          // constructor
          constructor(name, age) {
              // fields
              // 두 fields에 전달받은 name과 age를 할당
              this.name = name;
              this.age = age;
          }
    
          // methods
          speak() {
              console.log(`${this.name}: hello!`);
          }
      }
    
      const minji = new Person('minji', 20); // 새 object를 생성
      console.log(minji.name);
      console.log(minji.age);
      minji.speak(); // speak 함수 호출
    

    Console

    minji
    20
    minji: hello!

Object

  • class를 이용해 새로운 instance를 생성한 것
  • data를 넣었기때문에 메모리에 올라감
  • 여러 맛의 붕어빵들로 비유함

Getter and setters

  • class를 사용하는 사용자가 잘못된 값을 입력시 이에 대응할 수 있도록 getter/setter를 사용함
      class User {
          constructor(firstName, lastName, age) {
              this.firstName = firstName;
              this.lastName = lastName;
              this.age = age;
          }
          // getter
          get age() {
              return this._age;
          }
          // setter
          set age(value) {
              // 다소 공격적인 대응
              // if(value < 0) {
              //     throw Error('age can not be negative');
              // }
              // this._age = value;
    
              // 수정한 대응
              this._age = value < 0 ? 0 : value;
              // 나이는 음수 안 됨
              // 음수 입력시 0 반환
          }
      }
    
      const user1 = new User('Steve', 'Jobs', -1);
      console.log(user1.age);
    

    Console

    0
  • age라는 getter를 정의하는 순간, this.agegetter를 호출하게 됨.
  • age라는 setter를 정의하는 순간, =age; 가 할당되며 setter를 호출하게 됨.
  • 전달된 value는 setter안의 this._age에 할당되며, 메모리 값을 업데이트 함.
  • getter/setter에 쓰이는 변수의 이름(여기서는 _age)을 달리 사용해 call stack이 다 차는 것을 막을 수 있음

public, private

  • too soon!
  • public: constructor(생성자)를 사용하지 않고 field를 정의하면 외부에서 접근이 가능함
  • private: # 기호와 함께 field를 정의하면(# names: hash names로 발음) 클래스 내부에서만 접근, 변경이 가능함

      class Experiment {
          publicField = 2; // public
          #privateField = 0; // private
      }
      const experiment = new Experiment();
      console.log(experiment.publicField); // 2
      console.log(experiment.privateField); // undefined
    

    Console

    2
    undefined

static

  • too soon!
  • class가 가진 고유의 값과 반복 사용하는 method들을 object와 상관없이 class이름을 이용해 호출함

      class Article {
          static publisher = 'I am MINJI';
          constructor(articleNumber) {
              this.articleNumber = articleNumber;
          }
    
          static printPublisher() {
              console.log(Article.publisher);
          }
      }
    
      const article1 = new Article(1); // 새 object 생성
      const article2 = new Article(2); // 새 object 생성
      console.log(article1.publisher); // undefined
      // class(Article)로 호출해야 함
      console.log(Article.publisher);
      Article.printPublisher();
    

    Console

    undefined
    I am MINJI
    I am MINJI

Inheritance (상속)

  • extends 키워드를 사용하면 해당 클래스의 fields와 methods를 포함할 수 있음
  • overriding: 필요한 함수만 재정의해 사용함
  • overriding을 할 경우 부모의 함수는 더 이상 쓸 수 없게 됨
  • overriding했지만, 부모의 함수를 쓰고 싶다면, super. 를 사용해 부모 함수를 호출

      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;
          }
      }
    
      class Rectangle extends Shape {}
      class Triangle extends Shape {
          draw() { // overriding
              super.draw(); // 부모 함수의 draw() 호출
              console.log('🔺'); 
          }
          getArea() { // overriding
              return (this.width * this.height) / 2;
          }
          toString() { // object의 함수를 overriding
              return `Triangle: color: ${this.color}`
          }
      }
    
      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());
    

    Console

    drawing blue color!
    400
    drawing red color!
    🔺
    200

※ 참고: Inheritance in JavaScript - Web 개발 학습하기 | MDN

instanceOf

  • object instanceof class
  • 왼쪽의 object가 오른쪽의 class의 instance인지 확인함
  • boolean 반환

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

    Console

    true
    false
    true
    true
    true
    Triangle: color: red

※ JS에서 만든 모든 object class들은 JS의 Object를 상속함
⇒ 즉, 어떤 object든 공통적으로 존재하는 함수들을 사용할 수 있다는 말!
예시 코드의 Triangle class의 toString처럼 overriding해서 사용하면 됨

Standard built-in objects(표준 내장 객체)

※ 참고: Standard built-in objects - JavaScript | MDN

  • Value properties, Error objects, Indexed Collections, keyed collections, Promise, JSON 참고!

< 출처 >

“자바스크립트 6. 클래스와 오브젝트의 차이점(class vs object), 객체지향 언어 클래스 정리 | 프론트엔드 개발자 입문편 (JavaScript ES6),” 유튜브 비디오, 25:36, 게시자 “드림코딩 by 엘리,” 2020년 4월 27일, https://youtu.be/tJieVCgGzhs