자바스크립트에서 프로토타입은 아주 중요한 역할을 한다. 프로토타입은 생성자 함수가 실행되면서, 새로운 객체 인스턴스가 만들어질 때 프로토타입 객체가 지정된다.
prototype은 객체의 원형을 말한다. 우리가 흔히 사용하는 메서드들의 집합소이다. 배열의 메서드, 객체의 메서드, 함수의 메서드들이 여기 속해있다.
(배열의 프로토타입)
Array.prototype을 보면 우리가 사용하는 많은 메서드들이 prototype안에 들어있는 것을 알 수 있다.
마찬가지로 Object, Function 모두 prototype을 볼 수 있다.
__proto__는 모든 객체가 가지고 있지만, 실제로 보이지는 않는다. 이 __proto__는 자기 객체의 원형을 가르킨다. 즉, 객체원형의 prototype을 가르키는 것을 알 수 있다.
출력결과
실제로 arr 배열에 prototype 콘솔을 찍어보면 undefined가 출력되는 것을 볼 수 있고, __proto__의 콘솔을 찍어보면 무언가 콘솔이 나온다는 것을 알 수 있다.
실제 __proto__의 값을 vsCode에서 보고 싶다면
console.dir(arr.__proto__, { showHidden: true });
console.dir()로 볼 수 있다.
그렇다면 __proto__는 자기의 원형prototype을 기르킨다고 했는데, 실제로 그런지 확인 해보면
출력결과
true로 출력되는 것을 볼 수 있다.
결국 arr.__proto__의 원형은 Array.prototype이라는 것을 알 수 있다.
그런데 prototype은 객체의 인스턴스가 생성될때 프로토타입의 객체가 지정된다고 했는데, 위의 코드에서는 배열을 변수에 선언했을 뿐, 생성자 함수로 배열을 선언하지 않았다. 그런데 arr의 프로토타입 객체의 원형은 Array.prototype이다.
그 이유는 자바스크립트의 고유 문법으로써 실행된다. 이는 자바스크립트에서 배열이 Array 객체의 인스턴스로 간주되어서 배열이 생성될 때 Array.prototype으로 프로토타입이 지정된다.
이는 객체, 함수에도 동일하게 적용된다.
prototype을 우리가 가져다 쓰는 것은 물론 설정까지도 가능하다.
출력결과
위의 출력결과를 보면 위에서 Array.prototype에 새롭게 설정한 name이라는 프로퍼티를 배열 메서드로 사용할 수 있다는 것을 볼 수 있다.
기존의 메서드를 오버라이딩 할 수도 있다.
출력결과
기존 배열의 메서드인 map()함수를 오염시켜서 hi 가 출력되도록 바꾸었다.
위의 코드처럼 기존 메서드를 오버라이딩 할 수도 있다.
프로토타입 체인은 자바스크립트에서 모든 객체는 자신의 부모 역할을 하는 프로토타입 객체를 가지며, 이 프로토타입 객체는 또 다른 프로토타입 객체를 가질 수 있다. 이렇게 연결된 객체의 체인을 프로토타입 체인이라고 한다.
프로토타입 체인은 객체의 프로퍼티나 메서드에 접근할 때 사용된다. 만약 객체에서 해당 프로퍼티나 메서드를 찾지 못하면 자동으로 프로토타입 체인을 따라 상위 프로토타입 객체에서 찾게 된다. 이런 식으로 상위 프로토타입 객체에서 해당 프로퍼티나 메서드를 찾을 때까지 계속해서 체인을 따라 올라가게 된다. 만약 최상위 프로토타입 객체에서도 찾지 못하면 null이 반환된다.
위의 코드는 Child라는 클래스는 Parent의 부모 클래스를 상속받았고 Parent클래스는 프로토타입에 say라는 함수를 새롭게 정의하였다. 그런데 test인스턴스에서 say()함수가 실행되는 것을 볼 수 있다. 왜 그런 것일까?
우선 test.__proto__가 가르키는 prototype은 어디일까?
출력결과
test인스턴스의 생성자 함수인 Child클래스를 가르키는 것을 알 수 있다. 하지만 이 Prototype에는 우리가 Parent.prototype에 정의한 say()함수는 찾아볼 수 없다.
프로토타입 체인을 따라 올라가보자.
출력결과
프로토타입 체인을 따라 한단계 위로 올라가보니 Parent class를 가르키는 것을 볼 수 있다. 그리고 이곳에 우리가 정의한 say()함수도 정의되어있는 것을 볼 수 있다.
이를 통해 프로토타입체인을 통해 상속하여 test 인스턴스에서도 say() 함수를 사용 할 수 있다는 것을 알 수 있다.