class 문법은 constructor, prototype 을 이용한 상속기능을 만들어주는 문법이다.
function부터 시작하던 문법과 기능상 차이는 크게 없지만 class를 이용하면 더욱 직관적이고 보기 쉽게 만들 수 있다
아래의 코드를 살펴보자
class 부모 {
constructor(){
this.name = 'Kim'
}
}
let 자식 = new 부모();
굉장히 간단하게 class를 이용한 상속기능을 만들어 보았다
function 부모(){} 어쩌구 저쩌구 이렇게 생성자 함수를 만드는 문법과 똑같은 문법이다
new 키워드를 이용해 부모라는 class 안에서 오브젝트를 생성할 수 있다.
constructor() 라고 쓴 부분에는 this.name this.age 등 적으면 새로 생성되는 오브젝트들에 값을 부여할 수 있다.
상속가능한 함수를 만들기 위해서는 두 가지 방법이 있다
- 함수를 consturctor 안에 추가하는 방법
- 생성자 함수의 prototype 안에 추가하는 방법
class 부모 {
constructor(){
this.name = 'Kim';
this.sayHi = function(){ console.log('hello') } //가능
}
}
let 자식 = new 부모();
위의 코드를 살펴보면 constructor 안에 함수를 추가했다.
그럼 이제부터 새로 생성되는 자식은 sayHi() 함수를 직접
가지게 되며 자유롭게 사용할 수 있다
class 부모 {
constructor(){
this.name = 'Kim';
}
sayHi(){
console.log('hello')
}
}
let 자식 = new 부모();
이번에는 constructor 안에가 아니라 밖에서 sayHi()라는 함수를 추가해줬다
이렇게 되면 생성자 함수 prototype 안에 sayHi()라는 함수가 생겨나는데 class를 통해 생성되는 새로운 자식 객체들은 prototype 덕분에 sayHi()라는 함수를 사용할 수 있게 된다.
즉, 1번과 2번의 공통점은 새로 생성되는 자식 객체들이 sayHi()라는 함수를 사용할 수 있다는 것.
차이점은 1번을 통해 만들게 되면 자식 객체가 sayHi()를 직접 갖게 되고
2번을 통해 만들게 되면 부모의 prototype 안에 sayHi()가 있기 때문에 참조해서 사용할 수 있다는 것이다
**참고로 Object.getPrototypeOf(자식) 을 사용하면 부모 prototype을 출력해준다
proto라는 키워드와 비슷한 역할을 한다
ES6 방식으로 constructor 만들 때 파라미터를 추가하려면
class 부모 {
constructor(이름, 나이){
this.name = 이름;
this.age = 나이;
}
}
let 자식 = new 부모('Park', 30);
이런 식으로 하면 파라미터를 넣어서 constructor를 만들 수도 있다.
여기까지 class 문법을 이용한 상속기능을 만들어 보았다.
그렇다면 조금 더 나아가서 자바스크립트 객체지향 문법의 끝판왕인 extends에 대해서 알아보자
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
}
할아버지라는 class를 하나 만들어보았다.
할아버지 class는 성과 이름이라는 속성을 가지고 있는데 new 할아버지()를 통해 새로운 오브젝트를 생성할 수 있다
근데 만약 이 class가 너무 유용해서 이것과 유사한 class를 만들고 싶다면 어떻게 해야 할까?
그럴때 extends를 사용하면 매우 쉽게 만들 수 있다!
쉽게 말하면 extends는 다른 class를 상속해서 만들 수 있게 도와주는 문법이다
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
}
class 아버지 extends 할아버지{
}
할아버지를 extends한 아버지라는 새로운 class를 만들었다
그럼 이제 할아버지라는 class를 그대로 복사한 아버지라는 class가 생성된다
당연히 아버지 constructor안에 내용을 추가하면 된다
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
}
class 아버지 extends 할아버지{
constructor(){
this.나이 = 50;
}
}
let 오브젝트 = new 아버지();
console.log(오브젝트)
한 번 출력해보자!
띠용 에러가 난다
해석해보면 constructor 안에 super를 써야 한다고 에러가 난다
그럼 넣어주면 된다
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
}
class 아버지 extends 할아버지{
constructor(){
super();
this.나이 = 50;
}
}
let 오브젝트 = new 아버지();
console.log(오브젝트)
super()라는 함수는 extends로 상속중인 부모 class의 constructor()를 의미한다
쉽게 말하면 할아버지 class의 constructor() 이거랑 똑같다는 소리이다
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
}
class 아버지 extends 할아버지{
constructor(){
super() == constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
this.나이 = 50;
}
}
let 오브젝트 = new 아버지();
console.log(오브젝트)
이렇게 super를 추가해줘야 에러가 나지 않고 아래와 같이 잘 출력이 된다
근데 할아버지 class의 constructor()에는 name 파라미터를 입력할 수 있었다
똑같이 상속을 받고 싶다면 할아버지가 가진 모든 속성들을 넣어줘야 정확히 상속 받을 수 있다
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
}
class 아버지 extends 할아버지{
constructor(){
super(name)
this.나이 = 50;
}
}
let 오브젝트 = new 아버지();
console.log(오브젝트)
할아버지 constructor()에 name이라는 파라미터가 있던걸 그대로 아버지 constructor()에도 따라했다.
이제 그럼 new 아버지(); 할 때 파라미터를 입력하면 this.이름 속성에 들어가게 된다.
할아버지 class 안에 함수를 추가한다면 아버지 class의 자식들도 물려받아 쓸 수 있을까?
class 할아버지{
constructor(name){
this.성 = 'Kim';
this.이름 = name;
}
sayHi(){
console.log('안녕 나는 할아버지')
}
}
class 아버지 extends 할아버지{
constructor(name){
super(name);
this.나이 = 50;
}
}
let a = new 아버지('만수');
그럼 이제 a라는 오브젝트는 sayHi()라는 함수를 쓸 수 있다
왜일까?
a라는 오브젝트가 a.sayHi() 이렇게 사용한다면
- a라는 오브젝트에 sayHi가 있는지 물어보고
- 없으면 아버지.prototype에 sayHi가 있는지 물어보고
- 없으면 할아버지.prototype에 sayHi가 있는지 물어보고
이런 식으로 sayHi를 실행하기 위해 부모님을 뒤져본다.
근데 sayHi()라는건 할아버지.prototype에 추가된 함수이기 때문에
a라는 오브젝트는 sayHi() 함수를 실행할 수 있는 것이다.
사실 그동안 class 문법을 여기저기서 찾아볼 수 있었는데 스스로 사용하기 조금 까다롭다고 여겼는지 그동안 눈길 조차 주지 않았다
그래서 매번 나중에 공부해야지 하며 미뤘었는데 더이상은 class의 애처로운 눈빛을 차마 외면하지 못 하고 열심히 정리하고 공부해봤다
prototype, constructor에 대해 어느정도 이해하고 있기 때문일까
생각보다,, 간단하네,,?