proto, constructor, prototype 이 각각 어떤 관계를 가지고 있는지 조사해봅니다.
function Animal() {} // 생성자 함수(constructor)
let animalObject = new Animal(); // 인스턴스 생성
위 그림에서 보듯이 function Animal() {}로 함수를 선언하면 그 밑에 prototype이란 속성은 자동으로 생성된다. prototype이란 속성을 생성한 자를 constructor라 부른다.
즉, Animal.prototype.constructor === fuction Animal()
정리해보면 prototype은 constructor의 한 속성이며 원형 객체로써의 의미를 지니고, proto는 상속을 해준 prototype 객체를 가리킨다.
모든 객체의 최상위의 prototype은 Object.prototype 이다.
최상위이므로 더이상 상속을 해준 객체가 없을 것이다.
즉, Object.prototype.proto === null 이다.
function Animal() {
this.eyes = 2;
this.nose = 1;
this.mouth = 1;
}
Animal.prototype.speak = function() {
console.log('blah blah');
}
// 상속받을 함수 Dog
function Dog() {
Animal.call(this); // Animal 함수의 속성들을 상속.
this.legs = 4;
}
Dog.prototype = Object.create(Animal.prototype); // Animal.prototype에 있는 메소드 상속
Dog.prototype.constructor = Dog; // 바로 윗줄로 인해 Dog.prototype.constructor = Animal로 되어 있어 그 부분을 수정
위의 코드와 같이 Animal이란 생성자 함수를 생성하고 그 prototype에 speak란 메소드를 작성했고,
이를 상속받을 Dog란 생성자 함수의 속성과 메소드가 온전히 메소드를 상속받을 수 있도록 코드를 작성했다.
class Animal {
constructor() {
this.eyes = 2;
this.nose = 1;
this.mouth = 1;
}
speak() {
console.log('blah blah');
}
}
// 상속받을 클래스 Dog
class Dog extends Animal {
constructor() {
super(); // 클래스 Animal의 속성과 메소드를 모두 상속받아옴.
this.legs = 4;
}
ES6 class를 쓰니 코드가 훨씬 짧고 깔끔해 졌다.
Animal.call(this)
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
이 세줄의 코드는 ES6 class에서
super();
이거 한줄로 해결된다. 물론 class 자식 extends 부모로 표기는 해줘야 super명령이 작동한다.
! class를 만드는 것 만으로도 캡슐화는 구현된 것이고 속성명과 메소드명을 최대한 간단하고 공통적인 것만 생각해서 써주면 추상화가 구현되고 상속는 위의 코드를 써주면 구현되고 다형성은 앞으로 실습할테지만 자식 클래스에서 부모클래스의 메소드의 내용을 수정하면 구현된다!