클래스는 생성자 함수와 매우 유사하지만 몇가지 다른 점이 존재한다.
1-1 new 연산자 없이 호출하면 에러. 생성자 함수는 일반 함수로서 호출.
1-2 클래스는 상속을 지원하는 extends와 super 키워드를 제공.
1-3 클래스는 호이스팅이 발생하지 않는 것 처럼 동작.
1-4 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행. 해체할 수 없다.
1-5 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어트리뷰트 [[Enumerable]] 값이 false이다. 열거되지 않는다.
클래스는 일급 객체로 아래와 같은 특징이 존재한다.
2-1 무명의 리터럴로 생성이 가능하다. 런타임에 생성이 가능하다.
2-2 변수나 자료구조(객체,배열 등)에 저장할 수 있다.
2-3 함수의 매개변수로 전달할 수 있다.
2-4 함수의 반환 값으로 사용할 수 있다.
함수의 몸체에는 0개 이상의 메서드만 정의할 수 있고, constructor(생성자), 프로토타입 메서드, 정적 메서드 세가지가 있다.
class Person {
// 생성자
constructor(name){
// 인스턴스 생성 및 초기화
// constructor 이름 변경 불가능, 복수 사용 불가능
// 내부에서는 return 문 반드시 생략.
this.name = name; // name 프로퍼티는 piblic 하다.
}
// 프로토타입 메서드
// 클래스는 prototype 프로퍼티에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 된다.
// 클래스가 생성한 인스턴스는 프로토타입 체인의 일원이 된다.
sayHi(){
console.log(`Hi! My name is ${this.name}`);
}
// 정적 메서드
// 인스턴스를 생성하지 않아도 호출할 수 있는 메서드.
static sayHello(){
console.log('Hello!');
}
}
// 인스턴스 생성
const me = new Person('Lee');
// 인스턴스의 프로퍼티 참조
console.log(me.name); // Lee
// 프로토타입 메서드 호출
me.sayHi(); // Hi! My name is Lee
// 정적 메서드 호출
Person.sayHello() // Hello!
클래스는 클래스 정의 이전에 참조할 수 없다. 다만 호이스팅은 발생한다. ( let과 const 처럼 일시적 사각지대에 빠진다.) 접근자 프로퍼티, 즉 접근자 함수인 getter setter 함수를 사용할 수 있다.
자바스크립트에서 클래시 플드는 기본적으로 public 하기 때문에 외부에 그대로 노출된다. (최신 브라우저, node js 등에서 private 하게 사용할 수 있는 방법이 업데이트 되었다. 필드의 선두에 #을 붙여주는 방식)
class Person {
constructor(name){
this.name = name // 인스턴스 프로퍼티는 기본적으로 public하다.
}
}
const me = new Person('Lee');
console.log(me.name); // Lee
static 키워드를 사용하요 정적 메서드는 정의하여도 정적 필드를 정의할 수는 없었으나 최신 브라우저, node js 등에서 private 하게 사용할 수 있는 방법이 업데이트 되었다.
클래스는 상속에 의해 기존 클래스를 상속받아 새로운 클래스를 확장하여 정의할 수 있다.
// 서브 클래스에게 상속된 클래스, 수퍼클래스라 부른다.
class Animal {
constructor(age, weight) {
this.age = age;
this.weight = weight;
}
eat() { return 'eat';}
move() { return 'move';}
}
// 상속을 통해 Animal 클래스를 확장한 Bird 클래스
// 이를 파생 클래스, 자식 클래스라 부른다.
class Bird extends Animal {
fly() { return 'fly' }
}
const bird = new Bird(1,5);
console.log(bird); // Bird { age: 1, weight: 5 }
console.log(bird instancof Bird); // true
console.log(bird instancof Animal); // true
console.log(bird.eat()) // eat
console.log(bird.move()) // move
console.log(bird.fly()) // fly
function Base(a){
this.a = a;
}
// 생성자 함수를 상속받는 서브 클래스
class Derived extends Base {}
const derived = new Derived(1);
console.log(derived); // Derived{a:1}
class Base {
constructor(a,b) {
this.a = a;
this.b = b;
}
}
// 서브 클래스
class Derived extends Base {
// constructor(...args) {super(...args);} 와 같이 암묵적으로 constructor가 정의된다.
}
const derived = new Derived(1, 2);
console.log(derived); Derived { a:1, b:2}
9-2 super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다.
class Base {
constructor(name) {
this.name = name;
}
sayHi() {
return `Hi! ${this.name}`;
}
}
// 서브 클래스
class Derived extends Base {
sayHi() {
// super.sayHi 는 수퍼클래스의 프로토타입 메서드를 가리킨다.
return `${super.sayHi()}. how are you doing?`;
}
}
const derived = new Derived('Lee');
console.log(derived.sayHi()); // Hi! Lee. how are you doing?