지난 게시물의 Constructor 문법을 통해 비슷한 객체를 생성하는 행위를 객체지향 용어로 상속(inheritance)이라고 합니다.
기계라는 Constructor가 가진 name, age 속성들을 그대로 물려받아서 오브젝트를 하나 뽑아주는게 재산 물려주는 상속과 비슷하다고 해서 상속이라고 부릅니다.
근데 자바스크립트엔 constructor 말고도 상속기능을 구현할 수 있는 장치가 하나 더 있습니다. prototype이라는 것인데 알아보도록 합시다.
Constructor를 만드시면 prototype이라는 항목이 Constructor 안에 몰래 생성됩니다.
저희가 만든 기계(constructor)는 전부 prototype이라는 항목을 내부에 몰래 생성합니다.
function 기계(){
this.name = 'Kim';
this.age = 15;
}
var 학생1 = new 기계();
var 학생2 = new 기계();
console.log(기계.prototype);
그럼 뭔진 모르겠는데 뭔가 출력되긴하죠?
갑자기 알게된 prototype이라는 비밀 공간은 왜 존재하고 어디에 쓰는 거냐면 이것이 바로 부모의 유전자역할을 해주는 일종의 비밀 공간이라고 보시면 됩니다.
저희가 부모님의 유전자를 물려받아 비슷한 점이 많은 것처럼 prototype은 자식들이 물려받을 수 있는 유전자라고 생각하시면 됩니다.
기계.prototype은 기계의 유전자입니다. 기계.prototype 에 뭔가 변수나 함수가 들어가있다면 기계로부터 생성되는 새로운 오브젝트들(자식들)은 전부 그걸 그대로 물려받아 쓸 수 있습니다.
예를 들면 이렇게 됩니다.
function 기계(){
this.name = 'Kim';
this.age = 15;
}
기계.prototype.gender = '남';
var 학생1 = new 기계();
var 학생2 = new 기계();
console.log(학생1.gender); //'남'이 출력됩니다
기계의 prototype이라는 곳에 { gender : '남' } 이라는 key/value 한쌍을 저장했습니다.
기계의 prototype, 즉 유전자에 gender : '남'이라는 데이터를 추가한 것입니다.
이제 학생1, 학생2 같은 기계로부터 생성되는 모든 자식들은 gender라는 속성을 사용할 수 있습니다.
그래서 결론은 prototype 이라는 비밀 공간을 이용하시면 똑같이 상속기능을 만들 수 있습니다.
(참고)
- prototype에는 값을 여러개 부여할 수도 있고 심지어 함수도 집어넣으실 수 있습니다. object 자료처럼 다뤄주시면 됩니다.
- prototype에 추가된 데이터들은 자식들이 직접 가지는게 아니라 부모만 가지고 있습니다.
prototype의 특징
1. prototype은 constructor 함수에만 몰래 생성됩니다.
일반 object, array 이런거 만들어도 거기엔 prototype이 없습니다.
그럼 일반 object 같은걸 상속하고 싶으면 어떻게 하냐고요?
constructor 함수를 만들던가 아니면 Object.create()를 쓰거나 class를 쓰거나 셋 중 하나 하시면 됩니다.
2. 내 부모님 유전자를 찾고 싶다면 __proto__를 출력해보시면 됩니다.
부모로부터 생성된 자식 object들은 __proto__라는 속성이 있습니다.
이걸 출력해보시면 부모의 prototype이 출력됩니다. 그래서 __proto__는 부모의 prototype과 같은 의미입니다.
function 기계(){
this.name = 'Kim';
this.age = 15;
}
var 학생1 = new 기계();
console.log(학생1.__proto__);
console.log(기계.prototype);
학생1.__proto__
기계.prototype
각각 출력해보시면 똑같은게 나옵니다. 그래서 "__proto__는 부모 prototype을 의미한다" 라고 알아두시면 되겠습니다.
3. __proto__를 직접 등록하면 object끼리 상속기능을 구현가능합니다.
__proto__는 부모의 prototype을 의미한다 라고 했습니다.
그럼 어떤 object에다가 __proto__를 강제로 하나 설정해버리면 어떻게 될까요?
var 부모 = { name : 'Kim' };
var 자식 = {};
자식.__proto__ = 부모;
console.log(자식.name); // 'Kim'
지금 부모와 자식 object를 하나씩 만들었습니다.
그리고 셋째줄에서 자식의 __proto__에 부모를 집어넣었습니다.
그럼 자식의 부모 유전자는 { name : 'Kim' } 이라는 오브젝트가 되는 것입니다.
그렇게 되면 자식은 이제 자식.name 속성을 자유롭게 사용할 수 있습니다.
상속기능 구현을 이렇게도 할 수 있군요.
4. 콘솔창에 prototype 정보들이 항상 출력됩니다.
Constructor를 만들고 물려받는 객체를 만든 다음 콘솔창을 켜보세요.
그곳에서 살펴보면 우리가 설정해주지 않았지만 __proto__ 이란게 나옵니다. __proto__는 부모 객체의 유전자와 같은 것 입니다.그래서 이걸 항상 까보실 수 있습니다. 아마 기계.prototype이랑 똑같은 내용이 출력되겠죠.
그리고 기계.prototype의 __proto__도 조회가능합니다. (기계.prototype의 부모 유전자요)
이렇게 쭉 내 부모의 부모까지 탐색할 수도 있습니다.
탐색해보시면 모든 object 자료형의 조상은 Object() 라는 기계이며 (일명 Object.prototype) 모든 array 자료형의 조상도 Object()입니다. (중간에 Array()라는 부모도 있고요)
모든 함수 자료형의 조상도 Object() 입니다.(그래서 자바스크립트는 모든게 다 Object라고 말하는 것입니다.)
(참고) prototype의 동작원리 : 내장 함수는 어떻게 동작하는가?
학생1.toString(); 와 같은 내장 함수들을 사용가능한 이유는 Object라는 부모 constructor의 prototype에 toString() 함수가 존재하기 때문입니다. 즉 부모의 유전자를 prototype를 통해 상속받고 있기 때문입니다.
'Javascript' 카테고리의 다른 글
자바스크립트 Javascript : Class 상속기능 (0) | 2024.04.02 |
---|---|
자바스크립트 JavaScript : Object.create() (0) | 2024.04.02 |
자바스크립트 JavaScript : 생성자(Constructor) (1) | 2024.04.02 |
자바스크립트 JavaScript : Reference data type (0) | 2024.04.01 |
자바스크립트 JavaScript : Rest Parameters (1) | 2024.04.01 |