[JavaScript] Class

Hyunji·2022년 5월 11일
0

공부

목록 보기
24/35
post-thumbnail

Class란?

  • 자바스크립트에서 Class는 함수의 한 종류
class User {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    alert(this.name);
  }
}

// User가 함수라는 증거
alert(typeof User); // function

class User { ... } 문법 구조가 하는 일

  • User 라는 이름을 가진 함수를 만든다
  • 함수 본문은 생성자 메서드 constructor 에서 가져온다
  • 생성자 메서드가 없으면 본문이 비워진채로 함수가 만들어진다
  • sayHi 같은 Class 내에서 정의한 메서드를 User.prototype 에 저장한다

new User 를 호출해 객체를 만들고 객체의 메서드를 호출하면 메서드를 prototype 프로퍼티를 통해 가져온다
이 과정이 있기 때문에 객체에서 Class 메서드에 접근할 수 있다

위의 설명을 코드로 표현한다면?

class User {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    alert(this.name);
  }
}

// Class는 함수이다
alert(typeof User); // function

// 정확히는 생성자 메서드와 동일하다
alert(User === User.prototype.constructor); // true

// Class 내부에서 정의한 메서드를 User.prototype에 저장된다
alert(User.prototype.sayHi); // alert(this.name);

// 현재 prototype 에는 메서드가 두 개 이다
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

Class 기본문법

class MyClass {
  // 여러 메서드 정의 가능
  constructor() {
    ...
  }
  method1() {
    ...
  }
  method2() {
    ...
  }
  method3() {
    ...
  }
  ... 
}

클래스는 위와 같은 기본 문법을 사용해 만들 수 있다
클래스를 만들고 new MyClass() 를 호출하면 내부에서 정의한 메서드가 들어있는 객체가 생성 된다
객체의 기본 상태를 설정해주는 생성자 메서드 constructor()new 에 의해 자동으로 호출 되므로, 특별한 절차 없이 객체를 초기화 할 수 있다

ex)

class User {
  
  constructor(name) {
    this.name = name;
  }
  
  sayHi() {
    alert(this.name);
  }
  
}

// 사용법:
let user = new User("Minsu");
user.sayHi();

new User("Minsu") 를 호출하면 다음과 같은 일이 일어난다
1. 새로운 객체가 생성됨
2. 넘겨받은 인수와 함께 constructor 가 자동으로 실행된다. 이때 인수 "Minsu"this.name 에 할당된다

이러한 과정을 거친 후에 user.sayHi() 같은 객체 메서드를 호출할 수 있다

메서드 사이에는 쉼표가 없다!
Class 메서드 사이에 쉼표를 넣게 되면 문법 에러가 발생한다.
Class와 관련된 표기법은 객체 리터럴 표기법과 차이가 있다. Class에서는 메서드 사이에 쉼표를 넣지 않아도 된다.

Class는 단순한 syntactic sugar (편의 문법) 일까?

// class User 와 동일한 기능을 하는 순수 함수를 만들어보자

// 1. 생성자 함수를 만든다
function User(name) {
  this.name = name;
}
// 모든 함수의 prototype은 'constructor' 프로퍼티를 기본으로 갖고 있기 때문에
// constructor 프로퍼티를 명시적으로 만들 필요가 없다

// 2. prototype에 메서드를 추가한다
User.prototype.sayHi = function() {
  alert(this.name);
};

// 사용법
let user = new User("Minsu");
user.sayHi();

순수 함수로 Class 역할을 하는 함수를 선언하는 방법과 class 키워드를 사용하는 방법의 결과는 거의 같다

하지만 두 방법에는 중요한 차이가 몇 가지 있다

  1. class 로 만든 함수에는 특수 내부 프로퍼티인 [[IsClassConstructor]]: true 가 이름표처럼 붙는다

    • 이것만으로도 두 방법에는 분명한 차이가 있음을 알 수 있다
    • 자바스크립트는 다양한 경우에 [[IsClassConstructor]]: true 를 활용한다
    • 클래스 생성자를 new 와 함께 호출하지 않으면 에러가 발생하는데 이 때 [[IsClassConstructor]]: true 가 사용된다
    class User {
      constructor() {
      }
      
      alert(typeof User); // User의 타입은 함수이긴 하지만 그냥 호출할 수 없다
      User(); // TypeError: Class constructor User cannot be invoked without 'new'
    • 클래스 생성자를 문자열로 형변환하면 'class...'로 시작하는 문자열이 되는데 이때도 [[IsClassConstructor]]: true 가 사용된다
    class User {
      constructor() {
      }
    }
    
    alert(User); // class User { ... }
  2. class 에 정의된 메서드는 열거할 수 없다 (non-enumerable)

    • class의 prototype 프로퍼티에 추가된 메서드의 enumerable 플래그는 false 이다
    • for..in 으로 객체를 순회할 때, 메서드는 순회 대상에서 제외하고자 하는 경우가 많다
  3. class는 항상 use strict 모드로 실행된다

    • class 생성자 안 코드 전체엔 자동으로 use strict 모드가 적용된다

constructor() 란?

  • constructor() 메서드는 Class 의 인스턴스 객체를 생성하고 초기화 하는 특별한 메서드 이다

Syntax (구문)

constructor() {
  ...
}
constructor(argument0) {
  ...
}
constructor(argument0, argument1) {
  ...
}
constructor(argument0, argument1, ... , argumentN) {
  ...
}
...

설명

constructor 을 사용하면 다른 모든 메서드 호출보다 앞선 시점인, 인스턴스 객체를 초기화할 때 수행할 초기화 코드를 정의할 수 있다

class Person {
  
  constructor(name) {
    this.name = name;
  }
  
  introduct() {
    console.log(`Hello, my name is ${this.name}`);
  }
  
}

const otto = new Person('Otto');

otto.introduce();

Class에 생성자를 정의하지 않으면 기본 생성자를 사용한다
아무것도 상속하지 않는 기본 클래스 일 때의 기본 생성자는 빈 메서드 이다

constructor() {}

다른 클래스를 상속하는 경우, 기본 생성자는 자신의 매개변수를 부모 클래스의 생성자로 전달한다

constructor(...args) {
  super(...args);
}

따라서 다음과 같은 코드를 작성할 수 있다

class ValidationError extends Error {
  
  printCustomerMessage() {
    return `Validation failed :-( (details: ${this.message})`;
  }
  
}

try {
  throw new ValidationError("Not a valid phone number");
} catch(error) {
  if (error instanceof ValidationError) {
    console.log(error.name); // ValidationError 가 아니라 Error!
    console.log(error.printCustomerMessage());
  } else {
    console.log('Unknown error', error);'
    throw error;
  }
}

ValidationError Class 는 아무런 초기화 동작도 필요하지 않으므로 생성자를 별도로 명시하지 않았으며 대신 기본 생성자가 매개변수로 부모 Error Class의 초기화를 처리하고 있다

파생 Class에 직접 생성자를 정의할 경우, 부모 Class의 생성자를 호출하려면 직접 super() 를 호출해야 한다

"constructor" 라는 이름의 메서드는 하나의 Class에 오직 하나만 존재할 수 있다
두 개 이상의 constructor 메서드를 정의하면 SyntaxError 가 발생한다


https://ko.javascript.info/class
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor

profile
성장중인 개발자

0개의 댓글