본문 바로가기
프로그래밍/JavaScript

자바스크립트 핵심 개념 : prototype

by 소소로드 2020. 12. 20.

1. prototype의 개념

constructor라는 생성자 함수가 있을 때
new 연산자를 써서 instance를 만들면
생성자 함수의 prototype이라는 프로퍼티가 
instance의 __proto__라는 프로퍼티에 전달된다.
(전달된다는 건 __proto__를 prototype처럼 쓸 수 있다는 거겠지?)


즉, 생성자 함수의 prototype,
instance의 __proto__는 같은 객체를 참조한다.

그런데 __proto__는 생략할 수 있어서
마치 instance에 연결된 것처럼 동작할 수 있다.
(실제는 아니고, 이해를 돕기 위함)


이해를 돕기 위한 실제 데이터값으로 예시를 들면
Array생성자를 통해 [1,2,3]이라는 인스턴스를 만들었다.
Array라는 생성자를 보면 여러가지 메서드, 프로퍼티들이 존재한다.
이는 console.dir(Array)를 통해서도 확인이 가능하다.
생략이 가능하다 하니 [1,2,3]을 가리키는 셈이다.

그리고 이 중에 prototype이라는 프로퍼티가 __proto__에 연결되어 있는데,
prototype은 객체라서 여러 메서드를 사용할 수 있다.
이 이미지를 도식화한 것이 2번의 그림이다.

console.log([1,2,3]);

 (3) [1, 2, 3]
  0: 1
  1: 2
  2: 3
  length: 3
  __proto__: Array(0)
    concat: ƒ concat()
    constructor: ƒ Array()
    copyWithin: ƒ copyWithin()
    entries: ƒ entries()
    every: ƒ every()
    ......

[1,2,3]을 찍어보면 __proto__가 함께 들어있는데,
__proto__를 열어보면 위 prototype처럼 메서드가 나온다.


function Person(n, a) {
  this.name = n;
  this.age = a;
}
var me = new Person('김율프', 6);

이런 코드가 있을때, new Person~은 Person의 instance이다.

var meClone1 = new me.__proto__.constructor('김율프_클론1', 10);
var meClone2 = new me.constructor('김율프_클론2', 15);
var meProto = Object.getPrototypeOf(me);
var meClone3 = new meProto.constructor('김율프_클론3', 20);
var meClone4 = new Person.prototype.constructor('김율프_클론4', 25);
// 답은 모두 Person {name: "김율프_클론x", age: x} 이다.

즉,
[CONSTRUCTOR].prototype
[instance].__proto__
[instance]
object.getPrototypeOf([instance])
=> 이 네가지 방식에 의해 생성자함수의 프로토타입에 접근이 가능

[CONSTRUCTOR]
[CONSTRUCTOR].prototype.constructor

(Object.getPrototypeOf([instance])).constructor
[instance].__proto__
.constructor

[instance].constructor
=> 이 다섯가지 방식에 의해 생성자함수에 접근이 가능 (자기자신)
앞에서 constructor를 붙이면 된다.


이 그림과 대비해 보면서 다시 또 보고 또 보자.

이 그림과 대비해 보면서 다시 또 보고 또 보자.

 


2. prototype의 사용 방법

 function Person(n, a) {
   this.name = n;
   this.age = a;
 }
 var me = new Person('김율프', 6);
 var you = new Person('김세석', 20);

 me.setOlder = function() { // me의 age를 1살씩 올리도록 세팅
  this.age += 1;
 }
 me.getAge = function() { // me의 세팅한 나이를 가져옴
   return this.age;
 } 
 you.setOlder = function() { // you의 age를 1살씩 올리도록 세팅
  this.age += 1;
 }
 you.getAge = function() { // you의 세팅한 나이를 가져옴 
   return this.age;
 }
 

이 코드에서 현재 me와 you의 setOlder, getAge가 겹치게 된다.

 

 function Person(n, a) {
   this.name = n;
   this.age = a;
 }


 Person.prototype.seOlder = function() { // me와 you의 age를 1살씩 올리도록 세팅
  this.age += 1;
 }

 Person.prototype.getAge = function() { // me와 you의의 세팅한 나이를 가져옴 
   return this.age;
 }
 
  var me = new Person('김율프', 6);
 var you = new Person('김세석', 20);
 

person의 instance들은 전부 자신의 것처럼 setOlder, getAge를 사용할 수 있다.
즉, 위 그림에서 constructor 부분을 건드는 게 아니라
그 옆의 prototype을 건드는 것이다.

 


3. prototype 체이닝

그림에 대해 설명해보면,
앞서 설명한 것처럼 Array는 생성자함수이고
그 함수를 사용하여 [1,2,3]이라는 인스턴스를 만들어냈다.
그러면 Array.prototype이라는 또 다른 프로퍼티가 생성되고
이 프로퍼티는 __proto__를 가리키지만 생략이 가능해서
마치 자신의 것처럼 [1,2,3]을 사용할 수 있다.

그런데, Array.prototype은 객체이다.
객체라는 건 Object 생성자에서 생성된 인스턴스라고 볼 수 있고,
따라서 Object.prototype을 상속받아서 Array.prototype을 사용할 수 있게 된다.
배열 [1,2,3]은 Object.prototype에서도 자신의 것인냥 사용할 수 있다.
빨간색 선을 따라서 사용할 수 있는 것을 프로토타입 체이닝이라고 부른다.

그러니까 인스턴스에서 없는 것을 타고 올라가서 prototype에서 찾을 수도 있고,
prototype에서 없는 것을 Object쪽의 prototype에서 찾을 수도 있다.

다음으로 이 프로토타입 체이닝을 통해 클래스를 사용하는 방법을 올리겠다.

 

 

-정재남님의 자바스크립트 핵심 개념강의를 이해후 재정리한 것