Web Dev/JavaScript :: 자바스크립트

[JavaScript] 클래스(class)는 함수다

HJPlumtree 2021. 3. 23. 22:37

클래스란?

클래스는 특별한 함수(function)다.

오브젝트를 만들어주는 템플릿이다.

 

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

alert(typeof User); //function이 나온다

여기서 class User { ... }이 한일을 알아보자

1. function 이름 User란 놈을 만든다. function의 코드는 constructor 메소드에서 가져온다(constructor 메소드를 안만들어주면 비어있다고 가정된다).

2. class 메소드를 저장해준다, User.prototype 안에 있는 sayHi 처럼

 

new User 오브젝트가 만들어지고, 안의 메소드를 부르면, 프로토타입 안에서 가져온다. 그래서 오브젝트는 클래스 메소드에 액세스할 수 있다.

 

코드로 상관관계를 살펴보자

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

// 클래스는 function이다
alert(typeof User); // function

// 더 정확히는 constructor 메소드 그 자체다
alert(User === User.prototype.constructor); // true

// 메소드들은 User.prototype안에 있다
alert(User.prototype.sayHi); // alert(this.name);

// User.prototype에는 2개의 메소드가 있다.
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

 

function과 중요한 다른점이 있다

1. class로 만들어진 function은 특별한 프로퍼티 [[FunctionKind]]:"classConstructor"로 레이블이 지정된다.

보통 function과 달리 'new'가 꼭 붙어야 된다.

 

class User {
  constructor() {}
}

alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new'

2. 클래스 메소드는 열거할 수 없다. "prototype"의 모든 메소드에 대해 열거 가능 플래그가 false로 되어있다.

3. 클래스는 항상 'use strict'. 클래스안의 모든 코드는 strict mode로 여겨진다.

 

 

클래스 표현 방법

보통 함수와 마찬가지로 클래스도 정의하고, 전달, 반환, 할당 등을 할 수 있다.

let User = class {
  sayHi() {
    alert("Hello");
  }
};

 

Named Function Expressions와 비슷하게, 클래스도 이름을 가질 수 있다.

이름을 가지고 있을때 오직 클래스 안에서만 보인다.

// "Named Class Expression"

let User = class MyClass {
  sayHi() {
    alert(MyClass); // MyClass 이름은 오직 클래스에서 보인다.
  }
};

new User().sayHi(); // MyClass definition을 보여준다.

alert(MyClass); // 에러, MyClass 이른은 밖에서 안보인다.

 

클래스를 동적으로 "주문방식"으로 만들 수도 있다.

function makeClass(phrase) {
  // 클래스를 반환한다, 즉 불러질때 만들어진다
  return class {
    sayHi() {
      alert(phrase);
    }
  };
}

// 새 클래스 만들기
let User = makeClass("Hello");

new User().sayHi(); // Hello

 

Getters 와 Setters

literal object처럼 클래스도 getters, setters, computed properties를 포함할 수 있다. 

class User {

  constructor(name) {
    // settter 호출
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      alert("Name is too short.");
      return;
    }
    this._name = value;
  }

}

let user = new User("John");
alert(user.name); // John

user = new User(""); // Name is too short.

기술적으로, 이런 클래스 선언은 User.prototype에서 getter와 setter를 생성하여 작동된다.

 

 

클래스 필드(Class fields)

위에서는 메소드만 추가했었다.

"클래스 필드"는 어떤 프로퍼티든 추가할 수 있는 문법이다.

예를들어, name 프로퍼티를 class User에 넣으려면

class User {
  // name 프로퍼티 넣기
  name = "John";

  sayHi() {
    alert(`Hello, ${this.name}!`);
  }
}

new User().sayHi(); // Hello, John!

 

그냥 "="를 사용하면 된다.

차이점은 User.prototype이 아닌 개별 오브젝트에 설정된다.

class User {
  name = "John";
}

let user = new User();
alert(user.name); // John
alert(User.prototype.name); // undefined, 없다

 

더 복잡한 값을 줄 수도 있다.

class User {
  name = prompt("Name, please?", "John");
}

let user = new User();
alert(user.name); // John

 

 

정리하면

기본적인 클래스 문법을 이렇게 된다.

class MyClass {
  prop = value; // property

  constructor(...) { // constructor
    // ...
  }

  method(...) {} // 메소드

  get something(...) {} // getter 메소드
  set something(...) {} // setter 메소드

  [Symbol.iterator]() {} // 계산된 이름의 메소드
  // ...
}

 

하위 클래스를 만들기 위한 extends

extends 키워드는 하나의 클래스를 다른 클래스의 하위 클래스로 만드는데 쓰인다

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // 수퍼(super)클래스 constructor를 부르고, 이름을 넣어준다.
  }

  speak() {
    console.log(`${this.name} barks.`);
  }
}

let d = new Dog('Leo');
d.speak(); // Leo barks.

하위 클래스가 부모 클래스보다 우선된다.

하위 클래스에 'consturctor'가 있으면, super()을 먼저 부르고 "this"를 사용한다.

 

함수 베이스 "클래스"들도 extend 할 수 있다.

 

function Animal (name) {
  this.name = name;
}

Animal.prototype.speak = function () {
  console.log(`${this.name} makes a noise.`);
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

let d = new Dog('Leo');
d.speak(); // Leo barks.

// 하위 메소드가 부모 메소드보다 우선된다.

 

일반적인 오브젝트는 "확장"할 수 없다.

일반 오브젝트에서 상속을 받고 싶으면, Object.setPrototypeOf()를 사용한다

const Animal = {
  speak() {
    console.log(`${this.name} makes a noise.`);
  }
};

class Dog {
  constructor(name) {
    this.name = name;
  }
}

// 이걸 안해주면, TypeError가 나온다
Object.setPrototypeOf(Dog.prototype, Animal);

let d = new Dog('Leo');
d.speak(); // Leo makes a noise.

 

 

 

 

 

원문: Class basic syntax (javascript.info)