서론

지금까지 비슷한 여러객체를 만들기 위하여 우리는 생성자 함수를 사용했었다.

const User = function(name, age){
  this.name = name;
  this.age = age;
  this.myName = function(){
  console.log(this.name);
  };
};

const Joonyoung = new User("Joonyoung", 26);

하지만 생성자 함수가 아닌, 클래스(Class)를 사용해서 만들 수도 있다.


Class

클래스는 ES6에 추가된 스펙이고 아래와 같은 방식으로 사용한다.

class 예제

const User2 {
	constructor(name, age){
    	this.name = name;
    	this.age = age;
    }
  myName(){
  	console.log(this.name);
  }
}

const Joonyoung = new User("Joonyoung", 26);

new를 통하여 호출했을 떄, 내부에서 정의된 내용으로 객체를 생성하는 것은 동일하다.
class라는 키워드를 사용하고, 내부의 constructor가 존재한다.

  • constructor는 객체를 만들어 주는 생성자 메소드이다. new를 통해 호출하면 자동으로 실행된다!
  • constructor는 인수를 넘겨받을 수 있고, 안에는 객체를 초기화하기 위한 값이 정의된다.

myName()처럼 클래스 내의 정의한 메소드는 User의 프로토타입에 저장된다.

🙋🏻‍♂️ 생성자 함수로 만든 객체의 myName()은 객체 내부에 있지만, class를 이용해 선언한 객체의 myName()은 프로토타입에 정의되어있다.

  • 생성자 함수도 클래스처럼 동일하게 동작하게 만들기 위해서는.. 👇
User.prototype.myName = function(){
	console.log(this.name);
};

📌 무슨 말인지 모르겠다면 여기서 프로토타입을 공부하자..

그러면 왜 class를 쓰는거지?

맨 처음 생성자 함수를 이용해 객체를 생성하는 구문에 new를 빼고 실행을 한다면 무슨 일이 일어날까?

const User = function(name, age){
  this.name = name;
  this.age = age;
  this.myName = function(){
  console.log(this.name);
  };
};

const Joonyoung = User("Joonyoung", 26); // Joonyoung = undefined

코드 자체에는 문제가 없다. (에러를 출력하지 않음)
User 함수가 반환하는 값, 리턴문이 없기 때문에 아무것도 반환하지 않으니 undefined가 된것이고, 그 값이 Joonyoung에 들어간 것이다.

문제는 없지만 분명히 저 코드는 개발자가 의도한 코드는 아닐 것이고, 실수한 것이 분명하다.
하지만 에러라고 알아차릴 방법이 없는것도 사실이다.

하지만 클래스를 사용한 구문에 new를 뺴고 실행한다면 다음과 같은 타입 에러가 출력된다.

한마디로 클래스는 new없이는 실행이 불가능하다는 것이다.

class의 상속

클래스의 상속에는 extends라는 키워드를 사용한다.

class 상속의 예제

class User {
  constructor(name){
    this.name = name;
  }
  hello(){
  	console.log('안녕');
  }
}

class Joonyoung extends User {
  bye(){
    console.log('빠이염');
  }
}

const Dopal = new Joonyoung("두팔");

/*
Dopal {name: '두팔'}
👇
__proto__: User{
	constructor: class Joonyoung
	bye: hello()
    __proto__: {
    	constructor: class User
        hello: hello()
    }
}
*/

class 메소드 오버라이딩 (method overriding)

메소드 오버라이딩 (method overriding)의 예제

만약 User에서 정의한 메소드와 Joonyoung에서 정의한 메소드가 동일한 이름으로 존재한다면 어떻게 될까?

class User {
  constructor(name){
    this.name = name;
  }
  hello(){
  	console.log('안녕');
  }
}

class Joonyoung extends User {
  bye(){
    console.log('빠이염');
  }
  hello(){
  	console.log('안녕하냐!');
  }
}

const Dopal = new Joonyoung("두팔");

Dopal.hello(); // '안녕하냐!'

동일한 이름으로 메소드를 정의하면 덮어쓰게 된다.

하지만 부모의 메소드를 그대로 사용하면서 확장(extends)하고 싶다면 어떻게 해야할까?
super라는 키워드를 사용하면 된다.

메소드 오버라이딩 (method overriding)의 예제2 #super사용

class User {
  constructor(name){
    this.name = name;
  }
  hello(){
  	console.log('안녕');
  }
}

class Joonyoung extends User {
  bye(){
    console.log('빠이염');
  }
  hello(){
    super.hello();
  	// console.log('안녕하냐!');
  }
}

const Dopal = new Joonyoung("두팔");

Dopal.hello(); // '안녕'

super.method()로 부모 클래스의 정적 메소드를 사용할 수 있다.
이런 방식을 overriding이라고 한다.

constructor의 overriding 예제

class User {
  constructor(name){
    this.name = name;
  }
  hello(){
  	console.log('안녕');
  }
}

class Joonyoung extends User {
  constructor(){
    this.birthMonth = 7;
  }  
  bye(){
    console.log('빠이염');
  }
<}

const Dopal = new Joonyoung("두팔");

클래스의 컨스트럭터는 빈객체로 만들어주고, this로 이 객체를 가리키게 된다.
하지만 익스텐즈를 써서만든 자식 클래스는 빈객체가 만들어지고, this에 할당하는 작업을 건너뛰기 때문에 에러가 발생하는 것이다.

class Joonyoung extends User {
  constructor(name){
    super(name);
    this.birthMonth = 7;
  }  
  bye(){
    console.log('빠이염');
  }
}

따라서 항상 super 키워드로 부모클래스의 컨스트럭터를 실행해야한다.
또한 부모 클래스에서 받은 인수를 그대로 받아서 넘겨줘야 하는 작업을 해줘야, 부모클래스에서 상속받은 name이 undefined가 안뜨게 된다.

🙋🏻‍♂️ 아까 앞에서는 컨스트럭터 그런거 없이도 name에 unedfined가 안떳는데요;

  • 자바스크립트는 자식 클래스에 컨스트럭터가 없으면 해당 부분이 있는 것처럼 행동한다.
  • 한마디로 자식생성자는 부모생성자를 무조건 호출해야 하는 것이다.
  • 따라서 자식생성자에 컨스트럭터가 존재하면, super를 기용해서 호출해주고, this.property로 할당해야 한다.
profile
개인 이력, 포폴 관리 및 기술 블로그 사이트 👉 https://aimzero-web.vercel.app/

0개의 댓글