모던 자바스크립트 Deep Dive - 25장

박상은·2021년 10월 4일
0

요약

1. 클래스

자바스크립트도 C++처럼 클래스를 이용한 객체지향 프로그래밍 수행이 가능하다.
하지만 클래스라는 문법을 만들어놓은 것 뿐이지 실제로는 생성자함수와 프로토타입에 의한 설탕문법이다.

2. 클래스와 생성자함수의 차이점

  1. new없는 호출은 무조건 에러
  2. extendssuper키워드 사용
  3. 클래스는 항상 let과 같은 호이스팅이 일어남 ( 일시적 사각지대 존재 )
  4. 클래스내부는 항상 strict mode로 지정됨
  5. 클래스의 메서드는 모두 [[Enumerable]]false이다.

3. 클래스 정의

클래스도 일급객체다.

// 클래스 선언문
class Person {}

// 클래스 표현식
const Person = class MyClass {};

4. 클래스 형태

class Person {
  // 생성자
  constructor(name, firstText, lastText){
	this.name = name;
    this.fullText = firstText + lastText;
  }
  
  // 프로토타입 메서드
  say(){
	console.log("Hello, ", this.name);
  }
  
  // 정적 메서드
  static hi(){
	console.log("hi");
  }
  
  // 접근자
  get fullText(){
    return this.firstText + this.lastText;
  }
  set fullText(full){
    [this.firstText, this.lastText] = full;
  }
}

const person = new Person("john");
person.say();	// "Hello, john"
Person.hi();	// "hi"

4.1 생성자

생략시 constructor() {} 로 자동으로 생성됨
그리고 생성자 함수처럼 this값이 자동으로 빈 객체로 생성되고 각종 처리후 this값을 리턴한다.

4.2 정적 메서드

객체가 가지는 메서드가 아닌 클래스 자체가 가지는 메서드
즉, 프로토타입체인에 존재하는 메서드가 아니라서 객체에서 사용할 수 없음

function Person(name){
  this.name = name;
}
Person.hi = function() { console.log("hi"); };

Person.hi();	// "hi"

5. 상속

기존 클래스를 기반으로 새로운 클래스를 생성하는 것을 의미한다.
예를 들어 Animal클래스에 동물들이 공통적으로 가지는 특성을 넣고 Bird가 상속받아 자신만의 특성을 넣는 행위를 BirdAnimal을 상속받는다 라고 말한다.

5.1 생성자 함수로 상속 흉내

클래스의 extends를 사용하지 않고 생성자 함수로 상속을 구현하려면 많은 일을 직접 처리해야한다.
1. apply()를 통해 부모의 생성자 호출
2. Object.create()를 통해 자식의 프로토타입 교체
3. constructor를 직접적으로 교체

5.2 생성자

생략시 자동으로 생성되는 생성자가 존재함

5.3 super()

  • 호출시 부모클래스의 생성자가 호출됨
  • 참조시 부모클래스의 메서드를 호출가능함
  • 주의할점 자식클래스의 생성자를 생략하지 않은 경우 반드시 맨 처음 명시적으로 super()를 호출해야함

5.4 [[HomeObject]]

자신을 바인딩하고 있는 객체의 참조값을 가짐
단, ES6축약표현으로 정의된 함수만이 [[HomeObject]]를 가짐
5.3 super()에서 참조시 부모클래스의 메서드를 호출가능함이 가능한 이유가 [[HomeObject]]때문이다.

부모클래스의 메서드를 호출하기 위해서는 부모클래스의 프로토타입을 알아야하고,
부모클래스의 프로토타입을 알려면 부모를 상속받는 자식의 객체를 알면 프로토타입 체인을 통해서 알아낼 수 있다.

자식의 객체가 메서드를 호출하면 그 메서드는 [[HomeObject]]를 가지고 있고,
[[HomeObject]]는 자신을 바인딩하고 있는 객체의 참조값을 가지니까 그 참조값을 이용해서 부모의 메서드를 호출할 수 있는 것이다.

5.5 [[ConstructorKind]]

[[ConstructorKind]]을 통해서 부모클래스인지 자식클래스인지 구분할 수 있다.
부모클래스인경우 "base", 자식클래스인경우 "derived"로 설정된다.

5.6 상속의 실행흐름

자식클래스의 생성자를 명시적으로 작성할 때는 반드시 super()를 맨위에 넣어줘야 한다고 했었다.
그 이유는 자식클래스는 부모클래스에서 인스턴스 생성을 위임하기 때문이다.

  • 실행순서
    1. 부모클래스의 constructor호출 후 this바인딩 및 초기화
    2. 자식클래스의 constructor에서 this를 그대로 받아서 초기화
    3. 처리가 완료된 this값 반환

6. 상속의 간단한 예시

class Parent {
  constructor(x){
    this.x = x;
  }
  
  say() {
	return "Hi, ";
  }
}

class Children {
  constructor(x, y){
    // 부모클래스의 생성자 호출 즉, Parent의 constructor호출
    super(x);
    
    this.y = y;
  }
  // 생략시 아래의 생성자가 자동으로 생성됨
  // constructor(...args) { super(...args) }
  
  say() {
	return super.say() + "Hello, ";	// Hi, Hello,
  }
}

마무리

필드, 접근제한자, 생성자없이 사용하는 방법 등이 생성될 예정인것 같음

0개의 댓글