개인적으로 프로토타입은 자바스크립트에서 가장 중요한 개념이 아닐까 생각한다.
먼저, __proto__는 proto로 _빼고 표기하겠다. (마크다운 때문에...)
Prototype & Proto
prototype을 한 줄로 요약하면, 함수가 자식(함수가 만든 객체)과 공유하는 객체이다.
prototype 객체는 함수만 가질 수 있으며, 그 중에서도 객체를 만들 수 있는 생성자 함수에서 중요한 개념이다. 반대로 proto는 자식 객체가 부모의 prototype 객체를 가리키는 포인터이다.
자바스크립트에서 생성자 함수로 객체를 만들면, 만들어진 객체의 proto와 생성자 함수의 prototype이 연결된다.
예시)
const a = new Array()
생성자 함수 Array로 자식 a를 만들었다.
이 상황에서 prototype과 proto가 어떻게 되는지 보자.
변수 a는 생성자 함수 Array의 자식이다. 앞에서 proto는 부모의 prototype을 가리키는 포인터라고 했다.
따라서, a의 proto는 Array의 prototype이 될 것이다.
a.__proto__ === Array.prototype // true
이게 무슨 의미인지 아직은 와 닿지 않을거라고 생각한다.
Array.prototype은 무엇인가...?
일단은 "프로토타입은 부모가 자식과 공유하는 객체다" 라고 기억하고,
Array.prototype이 무엇인지 살펴보자.
// Array.prototype을 콘솔에 찍어본다.
console.log(Array.prototype)
// 결과
[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
concat: ƒ concat()
constructor: ƒ Array()
copyWithin: ƒ copyWithin()
entries: ƒ entries()
every: ƒ every()
fill: ƒ fill()
filter: ƒ filter()
find: ƒ find()
findIndex: ƒ findIndex()
flat: ƒ flat()
flatMap: ƒ flatMap()
forEach: ƒ forEach()
includes: ƒ includes()
indexOf: ƒ indexOf()
join: ƒ join()
keys: ƒ keys()
lastIndexOf: ƒ lastIndexOf()
length: 0
map: ƒ map()
pop: ƒ pop()
push: ƒ push()
reduce: ƒ reduce()
reduceRight: ƒ reduceRight()
reverse: ƒ reverse()
shift: ƒ shift()
slice: ƒ slice()
some: ƒ some()
sort: ƒ sort()
splice: ƒ splice()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
unshift: ƒ unshift()
values: ƒ values()
Symbol(Symbol.iterator): ƒ values()
Symbol(Symbol.unscopables): {copyWithin: true, entries: true, fill: true, find: true, findIndex: true, …}
__proto__: Object
위 결과에서 나타난 부분이 prototype이고 이것이 Array 함수가 자식과 공유하는 객체이다.
Array.prototype를 살펴보면 find, length, push, pop등 몇 가지 익숙한 메소드들이 눈에 띈다.
const a = new Array()
이렇게 배열을 선언했을 때,
우리는 a.push('1'); a.pop();
과 같이 배열의 메소드들을 사용할 수 있었는데,
그 이유는 바로 a의 proto와 Array의 prototype이 연결되어 있기 때문에 가능한 것이었다.
지금까지 Array 함수를 통해 proto와 prototype의 관계가 무엇인지 알아보았다.
다음에는 Object, Function 생성자 함수를 알아보자.