이미지 출처: 넥스트리소프트
타입 객체 프로토 타입은 두 가지를 의미합니다
생성자 함수(Constructor)의 멤버 prototype 속성
생성자 함수와 new 키워드로 만들어진 인스턴스(instance)를 생성자 함수(Constructor)의 prototype 속성(prototype)과 이어주는 링크인 프로토([[Prodotype]])
즉, 1번과 instance를 이어주는 프로토([[Prodotype]])
프로토([[Prodotype]])는 접근가능한 것이 아니기 때문에 실제 동작상 이미지는 아래와 같습니다.
이미지 출처: 코어 자바스크립트
.prototype)과 프로토([[Prototype]])의 관계아래의 from, isArray, of, ... , prototype은 배열의 생성자 함수 Array가 가지고 있는 프로퍼티입니다.
그 중 prototype 프로퍼티는 at(), concat(), ... 등의 매서드를 가지고 있습니다.
아래는 생성자 함수 Array의 인스턴스 [1, 2, 3] 배열이 가지고 있는 프로토([[Prodotype]])의 매서드입니다.
생성자 함수 Array가 가지고 있는 prototype과 인스턴스 [1, 2, 3]이 가지고 있는 프로토([[Prodotype]])의 매서드가 동일합니다.
이미지 출처: 코어 자바스크립트
그리고 prototype과 [[Prodotype]]가 가지고 있는 constructor 프로퍼티는 생성자 함수 Array()를 가리키고 있습니다.
따라서 내부적으로 아래의 코드 네 개가 같습니다.
1. Array // ƒ Array() { [native code] }
2. [1, 2, 3].constructor // ƒ Array() { [native code] }
3. [1, 2, 3].[[Prototype]].constructor
4. Array.prototype.constructor // ƒ Array() { [native code] }
실제로 [1, 2, 3].[[Prototype]].constructor는 입력해서 Array에 접근 할 수는 없습니다.
내부적으로 가리키고 있는 것을 표현한 것입니다.
밑에 나올 "4.instance로부터 prototype 프로퍼티에 직접 접근하는 법"을 참조해 주세요.
null과 undefined를 제외한 데이터에는 모두 생성자 함수가 존재합니다.
생성자 함수에는 데이터가 사용할 수 있는 메서드가 있고, 데이터의 프로토([[Prodotype]])를 이용해 생성자 함수의 프로토 타입(prototype)에 접근하여 메서드를 사용합니다.
아래의 이미지 처럼 배열 데이터에는 값과 length만 존재하고 메서드는 없습니다.
메서드는 위의 설명과 같이 프로토([[Prodotype]]) 통로로 가져와서 사용합니다.
이미지 출처: 코어 자바스크립트
위의 설명에서 사용한 예시들(배열)은 모두 참조형 타입의 데이터입니다.
기본형 타입의 데이터의 경우 메서드 호출 방식이 조금 다릅니다.
기본형 타입의 데이터가 사용할 수 있는 메서드를 보기 위해서는 기본형 타입의 데이터의 프로토([[Prodotype]])를 확인하면 됩니다.
그래서 console.dir로 문자 리터럴의 프로토([[Prodotype]]) 프로퍼티를 확인해 봤습니다.
아무것도 나오지 않았습니다.
문자나 숫자 리터럴 자체는 객체가 아닙니다.
따라서 문자 리터럴은 인스턴스가 아니므로 프로토([[Prodotype]])가 존재하지 않는 것입니다.
하지만 문자 리터럴로 메서드를 사용할 수 있습니다.
문자 리터럴에는 프로토([[Prodotype]])가 없는데 어떻게 String 생성자 함수의 프로토 타입(prototype)에 접근하여 메서드를 사용하는걸까요?
이유는 데이터 타입에 따른 메서드 호출 방식 차이가 있기 때문입니다.
프로토([[Prodotype]])가 존재하지 않을 때 메서드 호출 순서는 다음과 같습니다.
이미지 출처: 코어 자바스크립트
참조형 데이터는 처음부터 인스턴스이기 때문에 메서드를 호출할 때 기본형 타입의 데이터에서 사용한 방식을 거치지 않습니다.
instance에서 프로토 타입(prototype) 프로퍼티에 직접 접근하는 것을 알아보겠습니다.
프로토([[Prodotype]])가 프로토 타입(prototype)과 연결되어 있기 때문에 instance.[[Prodotype]]로 접근할 수 있을 것 같아 보입니다.
하지만 instance.[[Prodotype]]을 입력하면 에러가 납니다.

instance.[[Prodotype]] 대신 아래와 같이 입력하면 프로토 타입(prototype)에 접근할 수 있습니다.
// 공식적인 방법
1. Object.getPrototypeOf(instance)
// 비공식적인 방법
1. instance.__proto__
function Person(name, age) {
this.name = name;
this.age = age;
}
// Person.prototype에 접근
const zima = new Person('robot', 100);
const mk0 = new Person.prototype.constructor('robot', 100);
const mk1 = new zima.constructor('robot', 80);
const mk3 = new Object.getPrototypeOf(zima).constructor('robot', 60);
const mk3 = new zima.__proto__.constructor('robot', 40);
Person 생성자의 인스턴스인 zima와 blue에 setOlder와 getAge 메서드를 각각 만들었습니다.
function Person(name, age) {
this.name = name;
this.age = age;
}
const zima = new Person('robot', 100);
const blue = new Person('AI', 1);
// Person의 instance를 만들고 해당 instance에 각각 메서드 추가
zima.setOlder = function() {
this.age += 1;
}
blue.setOlder = function() {
this.age += 1;
}
zima.getAge = function() {
return this.age;
}
blue.getAge = function() {
return this.age;
}
위의 코드와 동일하지만 코드를 줄이는 방법이 있습니다.
setOlder와 getAge 메서드를 인스턴스에 하나하나 추가하기보다 Person 생성자의 Prototype에 추가하는 것입니다.
Person 생성자의 Prototype에 추가된 메서드는 [[Prototype]]을 통해 새로 생성되는 모든 인스턴스에서 사용할 수 있습니다.
function Person(name, age) {
this.name = name;
this.age = age;
}
// Person에 instance에서 사용할 메서드 추가
Person.prototype.setOlder = function() {
this.age += 1;
}
Person.prototype.getAge = function() {
return this.age;
}
// 인스턴스는 Person에 미리 추가된 메서드 사용 가능
const zima = new Person('robot', 100);
const blue = new Person('AI', 1);
prototype 프로퍼티 역시도 객체입니다.
객체인 prototype 프로퍼티도 Object 생성자 함수의 new 연산으로 생성된 인스턴스가 됩니다.
따라서 prototype 프로퍼티가 인스턴스라면 prototype 프로퍼티는 프로토([[Prototype]])를 갖습니다.
prototype의 프로토([[Prototype]])는Object 생성자 함수의 prototype 프로퍼티와 연결되어 있습니다.
이렇게 prototype 프로퍼티가 연결되어 있는 것을 프로토 타입 체인이라고 합니다.
이미지 출처: 코어 자바스크립트
위와 같은 방식으로 모든 데이터는 Object 생성자 함수의 prototype 프로퍼티와 연결되어 있습니다.
객체의 prototype에 있는 메서드는 프로토 타입 체이닝을 통해 모든 데이터 타입에서 적용할 수 있습니다.
반면 객체전용 메서드는 객체 생성자 함수에 직접 정의되어 있습니다.
// 객체전용 메서드는 instance가 아닌 Object로 사용
Object.assign(obj)
Object.create(obj)
Object.freeze(obj)
Object.keys(obj)
Object.getPrototypeOf(obj)
Object.values(obj)
...
이미지 출처: 코어 자바스크립트