자바스크립트는 프로토타입 기반의 언어이다. 이는 자바나 c++의 클래스 기반의 객체 지향과 비슷하나 사뭇 다르기 때문에 자바 스크립트에서 상속을 구현하는 여러가지 방식이 생겨났다. 물론 지금은 es6의 class를 이용해서 다소 편하게 상속을 구현할 수 있지만, 비교적 고전적인 방식인 Object.create 메서드와 this 바인딩을 Pseudo classical 방식을 이용한 상속 방식을 정리해본다.
// (1)
function Human(name, age) {
this.name = name;
this.age = age;
}
// (2)
Human.prototype.hello = function() {
console.log(`Hello my name is ${this.name}`);
};
// (3)
function Student(name, age) {
Human.call(this, name, age); // call super constructor.
}
// (4)
Student.prototype = Object.create(Human.prototype);
// (5)
Student.prototype.constructor = Student;
const person1 = new Student('park', 99);
console.log(person1 instanceof Student) // true
console.log(person1 instanceof Human) // true
person1.hello(); // Hello my name is Park
(1)_ 먼저 pseudo classical한 방식으로 Human 이라는 생성자 함수를 만들어준다. 생성자 (constructor)임을 알아볼 수 있게끔 첫 글자를 대문자로 작성하는 것이 관례이다. 이렇게 만들어진 생성자는 new 를 통해 호출할 수 있다.
(2)_ 생성자에 존재하는 prototype 속성, 즉 Human.prototype 에 hello 란 메소드를 추가해줬는데, 'Human'의 prototype 객체에 추가된 모든 요소들은 Human 생성자를 통해 생성된 객체에서 사용 할 수 있다. 그러나, 생성자의 prototype 이 아니라, 인스턴스 내부에 추가된 속성들은 해당 인스턴스에서만 사용할 수 있다.
(3)_ Student 생성자 내부에서 Human.call(this,~~) 을 호출하면 이때의 this는 현재 생성된 Student 인스턴스가 되고 생성된 Student 인스턴스를 Human 생성자의 this로 전달함으로 인해 Human 생성자 내부의 this.name = name 은 생성된 Student 인스턴스에 name, age 속성멤버를 추가하는 결과를 가져온다.
(4)_ Object.create() 메서드를 통해서 Student의 프로토타입 Human의 프로토타입 객체로 지정해 주었다. Object.create() 메서드를 사용하면 Human의.prototype 객체를 원본 객체로 하는 새로운 객체를 생성하고, 이 객체를 Student 프로토타입 객체로 할당해준다. 이로인해 자식 생성자 함수의 프로토타입 객체와 부모 생성자 함수의 프로토타입 객체 간의 프로토타입 체인, 즉 부모자식 관계가 형성된다.
(5)_ 4번 이후 시점에서 부모 생성자 함수 (Human)의 프로토타입 객체를 그대로 복제하여 할당했기 때문에, constructor가 다시 올바르게 Student를 가리키게 하기 위해서는 constructor를 재할당 해줘야한다.
( Student.prototype.constructor = Student;
constructor 재할당 전 )
( Student.prototype.constructor = Student;
constructor 재할당 후 )