fffo

클래스 본문

Programming/Javascript

클래스

gggs 2021. 10. 13. 11:33

클래스

클래스는 프로토타입의 문법적 설탕인가?

  • js는 프로토타입 기반 객체지향 언어로, 클래스가 필요 없는 객체지향 프로그래밍 언어임
  • 하지만 편의를 위해 ES6부터 클래스가 추가되었는데, 패러다임이 바뀐 것은 아니지만 기존의 프로토타입 기반 구현과 완벽히 동일하게 작동하진 않음
  • 클래스와 생성자 함수의 차이
    • 클래스는 호출시 new 연산자를 강제함
    • 클래스는 상속을 지원하는 extends와 super키워드 제공
    • 클래스는 호이스팅이 발생하지 않는 것처럼 동작함
    • 클래스 내 코드는 암묵적으로 strict mode가 지정되고 해제할 수 없음
    • 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어트리뷰트 [[Enumeralbe]]의 값이 false임
  • 클래스는 단순한 문법적 설탕(기능은 동일한 편한 방식)이 아닌 새로운 객체 생성 메커니즘으로 볼 수 있음

클래스 정의

  • class 키워드를 이용해 정의
  • 생성자 함수와 같이 파스칼 케이스를 사용해 명명
  • 일반적이진 않지만 함수와 같이 표현식으로 클래스 정의 가능, 이 때 무명 가능
  • 클래스는 함수이므로 일급 객체임
  • 클래스 몸체에 정의할 수 있는 메서드
    • constructor (생성자)
    • 프로토타입 메서드
    • 정적 메서드
class Person {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    console.log(`Hi! I'm ${this.name}.`);
  }

  static sayHello() {
    console.log('Hello!');
  }
}

const p1 = new Person('dlwlrma');
console.log(p1.name); // dlwlrma
p1.sayHi(); // Hi! I'm dlwlrma.
Person.sayHello(); // Hello!

메서드

constructor

  • 클래스가 평가될 때 constructor의 내용을 가진 함수 객체가 생성됨
  • constructor는 클래스 내에 유일해야 하고, 정의하지 않을 시 암묵적으로 빈 내용의 constructor를 생성함
  • 프로토타입의 constructor와 이름만 같을 뿐 전혀 관계 없음
  • constructor는 별도의 반환문을 갖지 않아야 함
    • 명시적으로 객체 반환 시 암묵적 this반환이 무시되고 원시 값 반환 시 원시 값이 무시됨

프로토타입 메서드

  • 클래스 몸체에서 정의한 메서드는 prototype 프로퍼티에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 됨

정적 메서드

  • 클래스 몸체에서 static 키워드를 붙여 정의한 메서드는 정적 메서드가 됨

클래스의 인스턴스 생성 과정

  1. 인스턴스 생성 및 this 바인딩
    • 빈 객체 생성, 프토토타입을 클래스의 prototype 프로퍼티가 가리키는 객체로 설정
    • this에 해당 빈 객체 바인딩
  2. 인스턴스 초기화 : constructor 내부 코드 실행
  3. 인스턴스 반환 : 인스턴스가 바인딩 된 this 반환

프로퍼티

인스턴스 프로퍼티

  • 인스턴스 프로퍼티는 원칙적으로는 constructor 내부에서 정의해야 함
  • 최근 사양의 js에서는 클래스 필드를 허용
class Person {
  constructor(){
    this.name = 'lee';
  }
}

const p1 = new Person();
console.log(p1.name); // lee
// 최근 사양의 js
class Person {
  name = 'lee';
}

const me = new Person();
console.log(me.name); // lee

접근자 프로퍼티

  • 생성자 함수와 동일
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  get fullName() {
    console.log(`${this.firstName} ${this.lastName}`);
  }
  set fullName(name) {
    [this.firstName, this.lastName] = name.split(' ');
  }
}

const p1 = new Person('myeongsuk', 'lee');

p1.fullName; // myeongsuk lee
p1.fullName = 'wlrma dl';
p1.fullName; // 'wlrma dl'

private필드 정의

  • 최근 사양의 js에서는 private 필드 정의 가능
  • 선언이나 참조할 때 식별자 선두에 #을 붙임
  • 반드시 클래스 몸체에 정의해야됨. contructor에 정의 시 에러 발생
접근 가능성 public private
클래스 내부 O O
자식 클래스 내부 O X
클래스 인스턴스를 통한 접근 O X
class Person {
  #name = '';
  constructor(name){
    this.#name = name;
  }
  getName() {
    console.log(this.#name);
  }
}

const p1 = new Person('dlwlrma');
p1.getName(); // dlwlrma
console.log(p1.#name); //SyntaxError: Private field '#name' must be declared in an enclosing class

static 필드 정의

  • 최신 사양의 js에서는 정적 메서드와 마찬가지로 정적 필드를 정의 가능
class MyMath {
  static PI = 22 / 7;
  static #count = 0;

  static increment() {
    return ++MyMath.#count;
  }
}

console.log(MyMath.PI); // 3.142857142857143
console.log(MyMath.increment()); // 1

'Programming > Javascript' 카테고리의 다른 글

ES6 함수의 추가 기능  (0) 2021.10.16
클래스 상속  (0) 2021.10.15
클로저  (0) 2021.10.11
실행 컨텍스트  (0) 2021.10.07
this  (0) 2021.10.06
Comments