[JS] 클래스와 인스턴스

Jiwon Yoo·2023년 3월 15일
0

프론트엔드

목록 보기
13/38

객체 지향 프로그래밍(OOP)이란 무엇일까?

객체 지향 프로그래밍(Object Oriented Programming)을 쉽게 비유하자면, 하나의 모델이 되는 템플릿을 만들고 그것을 베이스로 한 객체를 만들어 프로그래밍 하는 패턴이다.

자바스크립트는 프로토타입 기반(prototype-based) 객체 지향 언어다. ES5에서는 생성자 함수와 프로토타입, 클로저를 사용하여 객체 지향 프로그래밍을 구현하였으나, ES6부터 클래스가 도입되었다. ES6의 클래스가 기존의 프로토타입 기반 객체 지향 모델을 폐지하고 새로운 객체지향 모델을 제공하는 것은 아니다. 사실 클래스도 함수이며 기존 프로토타입 기반 패턴의 문법적 설탕(Syntactic sugar)이라고 볼 수 있다.

// ES5 생성자 함수
function Fruit(name) {
  this.name = name;
}
Person.prototype.whatIsIt = function() {
  return `That's ${this.name}`;
}

// ES6 클래스 선언문
class Fruit {
  // constructor(생성자)
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    return `That's ${this.name}`;
  }
}

클래스 정의

ES6 클래스는 class 키워드를 사용하여 정의한다. class 이름은 생성자 함수와 마찬가지로 파스칼 케이스를 사용하는 것이 일반적이다. 이렇게 말하면 생성자 함수와 차이가 없다고 생각할 수 있다. 하지만 중요한 차이가 있다. 클래스는 클래스 선언문 이전에 참조할 수 없다.

console.log(Foo); // ReferenceError: Cannot access 'Foo' before initialization

class Foo {}

호이스팅이 발생하지 않는 것은 아니다. 다만, let, const 키워드로 선언한 변수처럼 호이스팅 되기 때문에 클래스 선언문 이전에 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠져 호이스팅이 발생하지 않는 것처럼 동작한다.

인스턴스 생성

그렇다면 클래스를 정의해 어떻게 사용해야할까? 생성자 함수와 같이 new 연산자와 함께 클래스 이름을 호출해 클래스의 인스턴스 생성된다.

class Fruit {
  // constructor(생성자)
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    return `That's ${this.name}`;
  }
}

const pear = new Fruit();

이 때 new 연산자와 함께 호출한 Person은 클래스의 이름이 아니라 constructor(생성자)이다. 표현식이 아닌 선언식으로 정의한 클래스의 이름은 constructor와 동일하다. constructor는 new 연산자 없이 호출할 수 없다.

Constructor (생성자) & 클래스 필드(class field)

constructor는 인스턴스를 생성하고 클래스 필드를 초기화하기 위한 특수한 메소드이다. 클래스 필드(class field)는 클래스 내부의 캡슐화된 변수(a.k.a 데이터 멤버, 멤버 변수)를 말한다. 클래스 필드는 인스턴스의 프로퍼티 또는 정적 프로퍼티가 될 수 있다. 쉽게 말해, 자바스크립트의 생성자 함수에서 this에 추가한 프로퍼티를 클래스 기반 객체 지향 언어에서는 클래스 필드라고 부른다. constructor는 인스턴스의 생성과 동시에 클래스 필드의 생성과 초기화를 실행한다. 따라서 constructor는 생략 가능하지만, 클래스 필드를 초기화해야 한다면 constructor가 있어야 한다.

class Fruit {
  // constructor(생성자)
  constructor(name) {
    // this는 클래스가 생성할 인스턴스
    // name은 클래스 필드
    this.name = name;
  }
  sayHi() {
    return `That's ${this.name}`;
  }
}

const pear = new Fruit();

클래스 필드의 선언과 초기화는 반드시 constructor 내부에서 이루어져야 한다. constructor 내부에서 선언한 클래스 필드는 클래스가 생성할 인스턴스를 가리키는 this에 바인딩한다. 이로써 클래스 필드는 클래스가 생성할 인스턴스의 프로퍼티가 되며, 클래스의 인스턴스를 통해 클래스 외부에서 언제나 참조할 수 있다. 즉, 언제나 public이다.

profile
새싹 개발자 🌱

0개의 댓글