자바스크립트는 프로토타입 기반 언어이다. 어떤 객체를 원형(prototype)으로 삼고 이를 복제함으로써 상속과 비슷한 효과를 얻는다.
var instance = new Constructor();
new 연산자와 함께 호출하면__proto__ 프로퍼티가 자동으로 생성되고,이를 그림으로 간단히 표현하면, 아래와 같다.

인스턴스가 사용할 메서드를 저장하는 객체이다.
ES5.1 명세에는
[[prototype]]으로 정의되어 있고instance.__proto__와 같은 방식으로 직접 접근하는 것은 허용하지 않는다.Object.getPrototypeOf(instance)메서드를 통해서 접근할 수 있는데 대부분의 브라우저에서__proto__접근 방법을 고수하여 호환성 차원에서 ES6에 도입했다.
function Person (name) {
this._name = name;
this.getName = function () {
return this._name
}
}
만약, 위와 같이 메서드를 prototype이 아닌 인스턴스에 생성할 경우, 생성자를 호출할 때마다 새로운 함수를 만들어 낸다.
const kim = new Person('kim');
const lee = new Person('lee');
console.log(kim.getName === lee.getName); // false
그렇기 때문에 객체의 원형인 prototype에 메서드를 저장한다.
Person.prototype.getName = function () {
return this._name;
}
메서드 내부의 this는 호출한 주체를 가리키기 때문에 호출할 때에는 __proto__를 생략한다.
// kim.__proto__.getName() // undefined
kim.getName() // kim

__proto__ 객체 내부에는 constructor 프로퍼티가 있으며 원래 생성자 함수(자기 자신)을 참조한다.이는 인스턴스로가 자신의 생성자 함수가 무엇인지 알고자 할 때 필요한 수단이기 때문이다.
var arr = [1, 2];
Array.prototype.constructor === Array // true
arr.__proto__.constructor === Array // true
arr.constructor === Array // true
var arr2 = new arr.constructor(3) // [3]
배열의 내부 구조를 보면 __proto__ 객체에 배열 메서드가 존재하고, 또다시 __proto__가 존재한다. 이는 객체의 __proto__이며 "prototype 객체가 객체"이기 때문에 Object.prototype과 연결된다.
이처럼 __proto__가 연쇄적으로 이어진 것을 프로토타입 체인이라 한다.

만약 객체에서만 사용할 메서드를 만들어 Object.prototype에 정의하면 어떻게 될까?
모든 prototype의 최상단에는 Object.prototype이기 때문에 다른 데이터 타입에서 호출할 수 있게 된다. 그렇기에 Object에 스태틱 메서드로 부여해야 한다.
만약 인스턴스가 prototype에 정의된 메서드와 동일한 이름의 메서드가 있다면, 인스턴스에 할당한 메서드가 호출된다.
이를 메서드 오버라이드라고 하며, 원본을 삭제하고 교체하는 것이 아니라 덮어씌운다는 이미지로 이해하는 것이 좋다.
덮어씌운다는 것이라면 어떻게 원본에 접근할까?
__proto__에 접근해 호출하되 호출 대상을 전달해준다.
var Person = function (name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
var kim = new Person('kim');
kim.getName = function () {
return this.name + '입니다.';
}
kim.__proto__.getName.call(kim) // kim
new 연산자로 Contructor를 호출하면 instance가 만들어지는데, 이 instance의 생략 가능한 프로퍼티인 __proto__는 Contructor의 prototype을 참조한다. Object.prototype에 도달한다.