본문 바로가기
Modern React Deep Dive/01장 리액트 개발을 위해 꼭 알아야 할 자바스크립트

1.3.2 클래스와 함수의 관계

by Whiimsy 2024. 4. 8.

1.3.2 클래스와 함수의 관계

클래스, 프로토타입

  • 클래스는 ES6에서 나온 개념으로, ES6 이전에는 프로토타입을 활용해 클래스의 작동 방식을 동일하게 구현할 수 있었음. 반대로 말하면, 클래스가 작동하는 방식은 자바스크립트의 프로토타입을 활용하는 것이라고 볼 수 있음. 클래스의 코드를 바벨에서 트랜스파일하면 다음과 같이 변환됨.
  • // 클래스 코드
    class Car {
      constructor(name) {
        this.name = name
      }
    
     honk() {
        console.log(`${this.name}이 경적을 울립니다!`)
      }
    
      static hello() {
        console.log('저는 자동차입니다')
      }
    
      set age(value) {
        this.carAge = value
      }
    
      get age() {
        return this.carAge
      }
    }
    
    // 바벨로 변환한 결과
    'use strict'
    
    // 클래스가 함수처럼 호출되는 것을 방지
    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError('Cannot call a class as a function')
      }
    }
    
    // 프로퍼티를 할당하는 코드
    function _defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i]
        descriptor.enumerable = descriptor.enumerable || false
        descriptor.configurable = true
        if ('value' in descriptor) descriptor.writable = true
        Object.defineProperty(target, descriptor.key, descriptor)
      }
    }
    
    // 프로토타입 메서드와 정적 메서드를 선언하는 코드
    function _createClass(Constructor, protoProps, staticProps) {
      if (protoProps) _defineProperties(Constructor.prototype, protoProps)
      if (staticProps) _defineProperties(Constructor, staticProps)
      Object.defineProperty(Constructor, 'prototype', { writable: false })
      return Constructor
    }
    
    var Car = /*#__PURE__*/ (function () {
      function Car(name) {
        _classCallCheck(this, Car)
    
        this.name = name
      }
    
      _createClass(
        Car,
        [
          {
            key: 'honk',
            value: function honk() {
              console.log(
                ''.concat(
                  this.name,
                  '\uC774 \uACBD\uC801\uC744 \uC6B8\uB9BD\uB2E4!',
                ),
              )
            },
          },
          {
            key: 'age',
            get: function get() {
              return this.carAge
            },
            set: function set(value) {
              this.carAge = value
            },
          },
        ],
        [
          {
            key: 'hello',
            value: function hello() {
              console.log('저는 자동차입니다')
            },
          },
        ],
      )
    
      return Car
    })()
  •  
  • ES6 미만 환경에서는 동작하지 않는 클래스를 구현하기 위해 _createClass라는 헬퍼 함수를 만들어 클래스와 동일한 방식으로 동작할 수 있도록 변경한 것을 확인할 수 있음. 위 코드를 조금 더 보기 쉽게 변경해보면,
  • var Car = (function () {
      function Car(name) {
        this.name = name
      }
    
      // 프로토타입 메서드. 실제로 프로토타입에 할당해야 프로토타입 메서드로 작동함.
      Car.prototype.honk = function () {
        console.log(`${this.name}이 경적을 울립니다!)
      }
    
      // 정적 메서드. 인스턴스 생성 없이 바로 호출 가능하므로 직접 할당.
      Car.hello = function () {
        console.log('저는 자동차입니다')
      }
    
      // Car 객체에 속성을 직접 정의.
      Object.defineProperty(Car, 'age', {
        // get과 set은 각각 접근자, 설정자로 사용할 수 있는 예약어
        // getter
        get: function () {
          return this.carAge
        },
        // setter
        set: function (value) {
          this.carAge = value
        },
      })
    
      return Car
    })()
  •  
  • 클래스 작동을 생성자 함수로 매우 유사하게 재현할 수 있음을 알 수 있음. 즉, 클래스는 객체지향 언어를 사용하던 다른 프로그래머가 좀 더 자바스크립트에 접근하기 쉽게 만들어주는, 일종의 문법적 설탕의 역할을 한다고 볼 수 있음. 또한 자바스크립트 클래스가 프로토타입을 기반으로 작동한다는 사실도 확인할 수 있음.