프로토타입과 클래스
- 클래스는 new 연산자 없이 호출하면 에러가 발생한다.
- 클래스는 extends와 super를 제공함. 생성자 함수는 제공하지 않음
- 클래스는 호이스팅이 발생하지 않는 것처럼 보이지만 생성자함수는 호이스팅이 된다.
- 클래스내의 모든 코드에는 암묵적으로 strict mode가 적용되며, 해제할 수 없다.
- 클래스의 constructor, 프로토타입메서드, 정적메서드는 모두 Enurmable 값이 false이다. 열거되지 않는다.
⇒ 클래스 문법은 프로토타입과 다른 새로운 객체 생성 매커니즘
클래스 정의
클래스는 함수다.
클래스는 표현식으로 정의할 수 있다.
클래스는 일급객체로서 다음과 같은 특징을 갖는다.
- 무명의 리터럴로 생성가능
- 변수나 자료구조에 저장할 수 있다.
- 함수의 매개변수에게 전달할 수 있다.
- 함수의 반환값으로 사용할 수 있다.
메서드
클래스의 몸체에는 0개 이상의 메서드를 정의할 수 있다.
메서드는
- 생성자
- 프로토타입메서드
- 정적메서드
3가지 이다.
프로토타입
var Person=(function(){
function Person(){
this.name=name;
}
Person.prototype.sayHi=function(){
console.log(`Hi my nameis ${this.name}`);
}
Person.sayHello(){
console.log("hi");
}
return Person;
}
클래스
class Person{
constructor(name){
this.name=name;
}
sayHi(){
console.log(`Hi my nameis ${this.name}`);
}
static sayHello(){
console.log("hi");
}
}
클래스 호이스팅
클래스 선언문으로 정의한 클래스는 함수 선언문과 같이 런타임 이전에 먼저 평가되어 함수 객체를 생성함
이때 평가된 함수 객체는 생성자함수이다.
함수 객체 생성시 프로토타입도 더불어서 생성된다.
단, 클래스는 클래스 정의 이전에 참조할 수 없다.
그래서 마치 호이스팅이 일어나지 않는 것 처럼 보이나, 호이스팅은 제대로 일어난다.(일시적 사각지대)
인스턴스 생성
클래스는 생성자 함수이며, new 연산자와 함께 호출되어 인스턴스를 생성한다. new 없이 사용하면 오류가 난다. 또한, 클래스의 식별자를 사용하지 않고 기명 클래스 표현식의 클래스 이름을 사용해 인스턴스 생성시에도 오류가 난다.
const Person=class Myclass{};
const p=new Myclass(); //Error
메서드
클래스 몸체에는 0개 이상의 메서드만 선언할 수 있다.
constructor
인스턴스를 생성하고 초기화 하기 위한 특수한 메서드이다.
constructor의 이름을 변경할 수는 없다.
constructor는 메서드로 해석되는게 아니라 클래스가 평가되어 생성한 함수 객체 코드의 일부가 된다. 클래스 정의가 평가되면 constructor의 동작을 하는 함수객체가 생성된다.
constructor는 암묵적으로 정의되어 생략할 수 있다.
생략시 빈 constructor에 의해 빈 객체를 생성한다.
constructor에 매개변수를 추가하여 인스턴스를 초기화 할 수 있다.
또한 별도의 반환문을 가지지 않아야 한다. 반환문이 없어야 해당 인스턴스인 this가 반환되기 때문이다.
프로토타입 메서드
클래스 몸체에서 정의한 메서드는 생성자 함수에 의한 객체 생성방식과 다르게 클래스의 prototype 프로퍼티에 메서드를 추가하지 않아도 프로토타입 메서드가 된다.
정적 메서드
정적메서드는 인스턴스를 생성하지 않아도 호출할 수 있다.
클래스에서는 static을 메서드 앞에 붙여 정적 메서드(클래스 메서드)를 만든다.
정적메서드는 인스턴스로 호출될수 없고, 클래스로 호출한다.
클래스의 인스턴스 생성과정
인스턴스 생성과 this바인딩
constructor 실행전에 암묵적으로 빈객체가 생성됨
해당 인스턴스의 프로토타입으로 클래스의 prototype 프로퍼티가 가리키는 객체가 설정됨
인스턴스는 this에 바인딩
인스턴스 초기화
인스턴스에 프로퍼티 추가, 초기값으로 인스턴스 프로퍼티 초기화
인스턴스 반환
모든 처리가 끝나면 this가 암묵적으로 반환됨
프로퍼티
인스턴스 프로퍼티
인스턴스 프로퍼티는 constructor 내부에서 정의해야함
인스턴스 프로퍼티는 언제나 public함
접근자 프로퍼티
자체적으로는 값이 아니나 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티
getter와 setter로 구성
getter는 호출하는 것이 아니라 프로퍼티처럼 참조하는 형식으로 사용
클래스 필드 정의 제안
클래스 필드를 다음과 같이 작성할 수 있음
class Person{
name="Lee";
}
const me = new Person();
클래스 몸체에서 클래스 필드를 정의하는 경우 this에 클래스 필드를 바인딩해서는 안됨
this는 constructor와 메서드 안에서만 유효하며, 참조시 반드시 this를 사용함
class Person{
name="Lee";
name(){
console.log(this.name); //Lee
}
}
클래스 필드는 초기값이 없다면 undefined가 됨
private 필드 정의 제안
#을사용하여 구현
class Person{
#name='';
constructor(name){
this.#name=name;
}
}
private필드는 반드시 클래스 몸체에서 정의해야함
private필드에 직접 접근은 불가능하므로 getter와 setter를 이용
static 필드 정의 제안
static private 필드를 정의할 수 있다.
static #num=0;
상속에 의한 클래스 확장
클래스 상속과 생성자 함수 상속
기존 프로토타입상속은 프로토타입 체인을 통해 다른 객체의 자산을 상속받는 것이나, 클래스확장은 기존 클래스를 상속받아 새로운 클래스를 확장하여 사용하는 것이다.
extends zldnjem
extends를 사용하여 상속할 수 있다.
이 역시 프로토타입을 통해 상속관계를 구현한다.
수퍼클래스와 서브클래스는 인스턴스의 프로토타입 체인뿐 아니라 클래스간의 프로토타입체인도 생성한다.
동적상속
extends 키워드 다음에는 클래스뿐 아니라 [[Construct]]내부 메서드를 갖는 함수 객체로 평가될 수 있는 모든 표현식을 사용할 수 있다.
function Base1(){};
class Base2{}
let condition=true;
class Derived extends (condition? Base1:Base2){}
const derived= new Derived();
서브클래스의 constructor
서브클래스에서 constructor를 생략하면 클래스에 다음과 같은 constructor가 암묵적으로 정의된다.
constructor(...args){ super(args); }
super키워드
super는 함수처럼 호출도 가능하고, 식별자처럼 참조할 수도 있는 특수한 키워드이다.
super를 호출하면 수퍼클래스의 constructor를 호출한다.
super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다.
주의사항
- 서브클래스에서 constructor를 생략하지 않는경우 서브클래스의 constructor에는 반드시 super를 호출해야한다.
- super호출전까지는 this를 참조할 수 없다.
- ⇒ 서브클래스는 인스턴스 생성을 수퍼클래스에게 위임한다.
super는 객체에서도 사용가능하다.
다만, 이는 ES6축약 표현으로 기재되었을 경우만 가능하다([[HomeObject]]가 있기때문)