우리가 저번시간 배웠던 내용은 객체지향 용어로 상속(inheritance)이라고 한다.
기계라는 constructor가 가진 name, age 속성들을 그대로 물려받아서 object 하나 뽑아주는게
재산 물려주는 상속과 비슷하다고 해서 상속이라고 부른다.
(그래서 상속해주는 것은 부모, 상속받는 object들은 자식이라고 많이 비유해서 부른다.)
근데 자바스크립트엔 constructor 말고도 상속기능을 구현할 수 있는 장치가 하나 더 있다.
prototype이라는 것인데 한번 알아보자.
prototype이라는 항목이 기계 안에 몰래 생성된다.▲ 위의 말이 진짜인지 확인하기 위해 출력해보자.
내가 만든 기계는 전부 prototype이라는 항목을 내부에 몰래 생성한다.
function machine(){
this.name = 'Kim';
this.age = 15;
}
let student1 = new machine();
let student2 = new machine();
console.log(machine.prototype);
그럼 뭔진 모르겠는데 뭔가 출력된다.

갑자기 알게된 prototype이라는 비밀 공간은 왜 존재하고 어디에 쓰는 거냐면..
이것이 바로 부모의 유전자역할을 해주는 일종의 비밀 공간이라고 보시면 된다.
prototype은 자식들이 물려받을 수 있는 유전자라고 생각하면 된다.
machine.prototype은 machine의 유전자이다.
machine.prototype 에 뭔가 변수나 함수가 들어가있다면
machine로부터 생성되는 새로운 object들(자식들)은 전부 그걸 그대로 물려받아 쓸 수 있다.
예를 들면 이렇게 된다.
저번 시간 예제 코드에 prototype 어쩌구 한줄을 추가해보자.
function machine(){
this.name = 'Kim';
this.age = 15;
}
machine.prototype.gender = '남';
let student1 = new machine();
let student2 = new machine();
console.log(student1.gender);//'남'이 출력됩니다

machine의 prototype이라는 곳에 { gender : '남' } 이라는 key/value 한쌍을 저장했다.
(prototype은 저렇게 object 자료형 다루듯이 하면 된다.)
machine의 prototype, 즉 유전자에 gender : '남'이라는 데이터를 추가한 것이다.
이제 student1, student2 같은 machine로부터 생성되는 모든 자식들은 gender라는 속성을 사용할 수 있다.
진짠지는 출력해보자.

gender라는 속성이 추가되어서 선택할 수 있는 옵션에 표시되는 것을 볼 수 있다.
그래서 결론은 prototype 이라는 비밀 공간을 이용하면 똑같이 상속기능을 만들 수 있다.
(참고)
prototype에는 값을 여러개 부여할 수도 있고 심지어 함수도 집어넣을 수 있다.object자료처럼 다뤄주면 된다.prototype에 추가된 데이터들은 자식들이 직접 가지는게 아니라부모만 가지고 있다.
도대체 왜 prototype에 추가한 데이터는 자식들이 자유롭게 가져다 쓸 수 있는지 알아보자.
자바스크립트는 obeject에서 데이터를 뽑을 때 확인하는 순서가 있다.
예를 들면
function machine(){
this.name = 'Kim';
this.age = 15;
}
machine.prototype.gender = '남';
let student1 = new machine();
let student2 = new machine();
console.log(student1.gender);
▲ student1.gender라고 사용하면 '남'이 출력된다. 그 이유는..
자바스크립트는 object에서 값을 출력할 때 이런 순서로 물어본다.
(1) student1에 직접 gender라는 값이 있는가?
(2) 그럼 부모 유전자에 gender라는 값이 있는가?
(3) 그럼 부모의 부모 유전자에 gender라는 값이 있는가?
(4) 그럼 부모의 부모의 부모의 유전자에 .. 그게 있는가?
자바스크립트는 이런 알고리즘으로 작동한다.
그냥 쉽게말하자면 object에서 값을 뽑을 때
student1이라는 object가 gender라는 값을 가지고 있지 않지만machine.prototype) 에 있는 gender라는 걸 출력할 수 있는 이유이다.자바스크립트 array, object 들에는 붙일 수 있는 내장함수들이 많다.
sort, push, toString, map, forEach 등 이런 것들을 array에 붙여서 사용가능한데 혹시 그 이유가 무엇일까?
결론부터 말하자면 매우 쉽다.
let arr = [1,2,3];
console.log( arr.toString() );//가능
내가 만든 array에 arr.toString() 이렇게 붙일 수 있는 이유는
내가 만든 array의 부모 유전자가 toString()을 가지고 있기 때문이다. (혹은 부모의 부모가!)
array나 object 자료형 만들 때 부모가 있긴 있다.let arr = [1,2,3];
let arr = new Array(1,2,3);
▲ 위 코드 두줄은 같은 완전 똑같은 의미이다.
위는 인간이 array 만드는 방식, 밑은 컴퓨터가 array 만드는 방식이다.
사람은 [] 그냥 대괄호쳐서 만드는데 내부적으로는 저렇게 new 키워드를 항상 이용해서 array/object를 만들어준다.
그럼 new Array() 이게 뭔뜻일까?
Array라는 기계로부터 자식을 하나 새로 뽑아주세요 라는 뜻이다.
그래서 Array로부터 생성된 자식들은 Array의 유전자에 부여되어있는 함수, 데이터들을 자유롭게 사용할 수 있다.
Array라는 기계의 유전자가 진짜 있는지 확인해보자.
console.log(Array.prototype);

우리가 평소에 쓰던 sort, map, push, forEach 이런 것들이 등장한다.
그래서 Array의 자식들은 전부 이런 함수들을 쉽게 가져다 쓸 수 있었던 것이다.
Object 자료형도 똑같이 new Object() 이런 식으로 만들어주기 때문에 부모의 prototype에 있던 함수들을 자유롭게 사용가능하다.
이것이 내장함수들의 비밀이었다.
Q. 그럼 prototype으로 상속시키는거랑
constructor로 상속시키는거랑 차이가 뭘까?A. 자식들이 값을 직접 소유하게 만들고 싶으면
constructor로 상속시키시면 되고
부모만 가지고 있고 그걸 참조해서 쓰게 만들고 싶으면prototype으로 상속시키면 된다.
보통은 그래서 상속할 수 있는 함수 같은 것들은prototype으로 많이 만들어놓는다.
우리가 일반 object, array 이런거 만들어도 거기엔 prototype이 없다.
그럼 일반 object 같은걸 상속하고 싶으면 어떻게 해야 할까?
constructor 함수를 만들던가.. 아니면 다음 시간에 알려주는 Object.create()를 쓰거나 Class를 쓰거나 셋 중 하나 하면 된다.
부모로부터 생성된 자식 object들은 __proto__라는 속성이 있다.
이걸 출력해보면 부모의 prototype이 출력된다.
그래서 __proto__는 부모의 prototype과 같은 의미이다.
진짜 그런지 한번 출력해보자.
function machine(){
this.name = 'Kim';
this.age = 15;
}
let student1 = new machine();
console.log(student1.__proto__);
console.log(machine.prototype);

student1.__proto__
machine.prototype
각각 출력해보시면 똑같은게 나온다.
그래서 "__proto__는 부모 prototype을 의미한다" 라고 알아두면 된다.
그냥 __proto__는 내 부모 유전자가 뭔지 유전자 검사하고 싶을 때 쓸 수 있는 그런 값이라고 생각하면 된다.
__proto__는 부모의 prototype을 의미한다 라고 했다.
그럼 어떤 object에다가 __proto__를 강제로 하나 설정해버리면 어떻게 될까?
부모님이 생겨버린다.
일종의 유전자 공학인데 한번 실험해보자.
let parents = { name : 'Kim' };
var child = {};
child.__proto__ = parents;
console.log(child.name);
지금 parents와 child object를 하나씩 만들었다.
그리고 셋째줄에서 child의 __proto__에 parents를 집어넣었다.
그럼 자식의 parents 유전자는 { name : 'Kim' } 이라는 object가 되는 것이다.
그렇게 되면 자식은 이제 `child.name` 속성을 자유롭게 사용할 수 있다.
상속기능 구현을 이렇게도 할 수 있다.
예제코드 적어놓은 다음에
콘솔창에서 student1 한번 출력해보자.
function machine(){
this.name = 'Kim';
this.age = 15;
}
machine.prototype.gender = '남';
let student1 = new machine();
console.log(student1)

그럼 콘솔창에 name도 나오고 age도 나올 텐데
이상한 __proto__ 이런 것도 나온다.

▲ proto가 뭘까. 부모의 유전자라고 했다!
그래서 이걸 항상 까볼 수 있다. 아마 machine.prototype이랑 똑같은 내용이 출력될 것 같다.
그리고 machine.prototype의 __proto__도 조회가능하다. (machine.prototype의 부모 유전자!)
이렇게 쭉 내 부모의 부모까지 탐색할 수도 있다.
탐색해보면 모든 object 자료형의 조상은 Object() 라는 기계이며 (일명 Object.prototype)
모든 array 자료형의 조상도 Object()이다. (중간에 Array()라는 부모도 있다!)
모든 함수 자료형의 조상도 Object() 이다.
(그래서 자바스크립트는 모든게 다 Object라고 말하는 것이다.)