Class
상속 구현Person 생성자 함수는 name, age property와 getName(), getAge() 메서드를 갖고 있다.
Employee 생성자 함수는 name, age, position property와 getName(), getAge(), getPosition() 메서드를 갖고 있다
👀 이를 코드를 통해 살펴보자
코드를 보면 알 수 있듯이 getName, getAge와 같이 겹치는 메서드를 확인 할 수 있다.
자 그렇다면, 중복을 제거해보자!
중복을 제거하기 위해서 겹치는 메서드는 상위인 Person에 놔두고 Employee에는 겹치지 않는 메서드만 남긴다.
즉 위 그림의 관계를 갖으면 된다.
왜냐하면, 이렇게 만든 Employee instance는 prototype chaining을 타고 Emloyee의 getPosition() 메서드도 사용할 수 있고,
한단계 더 위로 chaining을 타서 Person의 getName(), getAge() 메서드도 사용할 수 있다.
🤷♀️ 그렇다면 위 그림과 같이 구현하려면 어떻게 해야할까❓
Class
상속 구현 방법🔊 1단계
Employee.prototype = new Person()을 통해 Employee의 prototype
에 Person의 instance를 할당하면 된다.
다만 이게 전부는 아니고 추가로 한단계를 더 거쳐야 한다.
잘생각해보면 이 코드는 기존에 있던 Employee prototype
객체를 완전히 새로운 객체, 즉 Person의 instance로 대체하는 결과가 된다.
그래서 여타의 prototype
과 동일하게 동작하게 하기 위해서 본래 갖고 있던 기능을 다시 부여해 줄 필요가 있다. prototype
객체에는 자바스크립트가 기본적으로 constructor property
를 생성해주었던 것을 기억할 것이다.
constructor
에는 생성자 함수가 담겨있었다.
📢 2단계
즉, Employee prototype
의 constructor
는 Employee 라는 것을 부여해 줘야 한다. 이것을 코드로 나타내면 아래와 같다.
이렇게 하면 서로 다른 두개의 클래스가 슈퍼, 서브 클래스의 관계를 갖게된다.
다이어그램으로 표현하면 아래와 같다.
😎 코드를 통해 살펴보자
📌 주의할 점
만약 Employee.prototype.getPosition이 Employee.prototype = new Person(); 보다 먼저 선언된다면, 결국 Employee.prototype = new Person();로 인해 전혀 새롭게 객체인 Person의 instance로 바꾸기 때문에 의미 없는 행동이 되고 만다.
추상적이여야할 class의 prototype에 age, name과 같은 정보들이 담겨있다.
만약 gomu 객체의 name property를 지운 상태에서 getName 메서드를 호출하면 원래대로라면 undefined가 반환되어야 할 상황인데 prototype chaining을 타고 Person의 name이 반환된다.
이는 바람직한 상황이 아니다.
prototype chaining 상에는 메서드들만 존재하도록 바꾸고 싶다.
즉, 위 그림에서 색칠된 부분을 지우고 싶다.
어떻게 하면 좋을까❔
Bridge.prototype
와 Person.prototype
를 연결한다.
원래는 Person에 instance를 넣었는데, 대신에 Bridge라고 하는 빈 객체를 넣었다.
마지막으로 본래의 prototype
에 기능을 되살리기 위해서 constructor
를 연결해준다
👍 코드를 통해 살펴보자
Employee.prototype = new Person()에 의하면 Employee의 prototype은 Person의 prototype
을 상속받긴 하지만 그와 동시에 Person의 인스턴스가 되므로 name, age 프로퍼티가 존재하게 된다.
반면 Bridge.prototype = Person.prototype 에 의하면, 비어있는 Bridge 함수에 prototype
이 Person의 prototype
을 참조하게 된다. 그 상태에서 new Bridge()로 인스턴스를 생성하면, 해당 인스턴스는 Bridge함수가 비어있으므로 name, age 프로퍼티가 생기지 않은 채로 Bridge의 prototype, 즉 Person의 prototype을 상속받게 됩니다.
Person의 메서드를 상속받으면서 Employee만의 고유 메서드를 추가/변경하고자 하는 것이 '클래스 상속'의 목적
입니다.
어떤 변수 또는 프로퍼티에 객체를 할당할 경우,
해당 변수 또는 프로퍼티에는 원본 객체를 '참조복사'한 값이 할당됩니다.
그러니까 Employee.prototype에 Person.prototype을 대입하면
prototype는 객체이기 때문에, Employee.prototype에는 Person.prototype이 참조복사 됩니다.
이후에는 복사본 또는 원본 중 어느 쪽의 내용을 추가/변경/삭제하더라도 양쪽 모두에 결과가 반영됩니다.
즉 Person.prototype 객체와 Employee.prototype 객체가 완전히 동일한 객체가 되는 것입니다.
따라서 Employee의 인스턴스는 Person의 인스턴스와 결과적으로 똑같은 기능을 하게 됩니다.
상속(상위클래스/하위클래스)의 관계가 아닌,
완전히 동일한 메서드를 지닌 채 생성자만 다른 동등한 레벨의 클래스가 되는 것이죠.
예로, 이 상태에서 Person 인스턴스에서 getPosition을 실행하면
Person 클래스에는 원래 getPosition 메소드가 없음에도 불구하고 실행이 될 것입니다.
왜냐하면 Employee.prototype.getPosition을 정의할때 employee.prototype는 Person.prototype가 되기 때문이다.