__proto__
는 메서드 등을 체인을 타고 찾는데 사용되는 실제 객체이다.prototype
은 new
로 인스턴스를 만들 때 __proto__
를 생성하는 데 사용하는 객체다. function Foo() {}
console.log(new Foo().__proto__ === Foo.prototype); // true, 인스턴스의 __proto__와 함수의 prototype은 같다
console.log(new Foo().prototype === Foo.prototype); // false, 인스턴스의 prototype과 함수의 prototype은 다르다.
console.log(new Foo().prototype === undefined); // true, 인스턴스의 prototype은 undefined이다(즉, 없다?).
console.log(new Foo() instanceof Foo); // true
console.log(new Foo() instanceof Object); // true
console.log(new Foo().__proto__.__proto__ === Object.prototype); // true
console.log(Foo.__proto__ === Function.prototype); // true
console.log(new Foo().__proto__); // Foo.prototype과 동일하다
/* {constructor: ƒ}
constructor: ƒ Foo
[[Prototype]]: Object */
console.log(Foo.prototype.constructor); // Foo, 함수 정의 반환
console.log(Foo.prototype.__proto__); // {}, 빈 객체 반환, 함수이므로 root level인 Object.prototype을 가리킨다
prototype
프로퍼티를 추가한다. 해당 prototype
프로퍼티는 constructor
와 __proto__
라는 두 개의 프로퍼티를 가진 객체다.__proto__
는 안 보이고, [[Prototype]]
만 보여서 이건 또 뭐냐고 물을 수 있다. 사실 둘은 같은 것이다. 정확히 말하면, __proto__
는 [[Prototype]]
에 대하여 브라우저에서 지원하는 getter이다. [[Prototype]]
은 private 연결이므로 직접적으로 접근할 수 없다. prototype
프로퍼티는 인스턴스 내에서 사용할 수는 없고, 함수에서만 사용할 수 있다.__proto__
프로퍼티를 통해 함수의 prototype
프로퍼티를 참조한다.__proto__
프로퍼티는 더 상위의 Function의 prototype
프로퍼티를 참조한다. 따라서 서로 다른 함수의 __proto__
프로퍼티들을 비교하면 같음을 확인할 수 있다.prototype
프로퍼티는 저장되는 실제 객체인 __proto__
프로퍼티를 위한 청사진일뿐이다. 다른 말로 풀자면, prototype
은 생성자 함수(constructor functions)에서 사용되는 것이며, 이러한 정의를 담는 정확한 용어로 "prototypeToInstall"
로 했어야 오해가 없었을 것이다.__proto__
의 정의에 잘 맞는 용어는 "installedPrototype"
으로 했어야 이해하기 쉬웠을 것이다. 정리해서, 함수를 new
키워드를 사용하여 인스턴스를 만들면 다음과 같은 일이 발생한다.
function SetName(name) {
this.name = name;
}
const marco = new SetName("Marco");
__proto__
프로퍼티를 만들고, 그 __proto__
프로퍼티가 SetName의 prototype
을 가리키게 한다.SetName.prototype.constructor
(= SetName 함수정의)가 실행(execute)되며, 이러한 해당 함수정의에 따라 "Marco" 문자열을 전달받은 'name' 프로퍼티가 새 객체에 추가된다. marco
에 해당 새 객체(1번에서 만들어진)가 지정되어 반환된다.. __proto__
프로퍼티만을 제대로 갖고, 클래스와 생성자함수는 추가로 prototype
프로퍼티를 갖는다. 인스턴스의 __proto__
프로퍼티는 클래스나 생성자함수의 prototype
을 가리킨다. (사족을 덧붙이자면, 클래스와 생성자함수의 __proto__
프로퍼티는 root level의 Function.prototype
프로퍼티를 가리킨다.추가로 Function과 Object의 프로토타입 관계를 아담과 이브
에 빗대어 살펴보자.(SOF - __proto__
VS. constructor.prototype
)
Object
는 이브이고, Function
은 아담이다. 아담(Function
)은 그의 갈비뼈(Function.prototype
)을 사용하여 이브(Object
)를 창조하였다. 그러면 아담(Function
)은 누가 창조했는가? - 자바스크립트 언어를 만든 사람! -
따라서 아래와 같은 비교 결과가 모두 참이 된다.
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.prototype === Function.__proto__); // true, 그 위는 없다.
console.log(Object.__proto__ === Foo.__proto__); // true, 둘 다 Function.prototype을 참조한다.
class Foo {
hello() {return '안녕하세요'}
}
class Bar extends Foo{
#age;
constructor(){
super();
this.name = "마르코";
this.#age = 11;
}
getName(){return this.name + " 입니다"}
get age(){return this.#age }
static bye() {return '잘가요'}
}
const bar = new Bar();
console.dir(Foo);
console.dir(Bar);
console.dir(new Foo());
console.dir(new Bar());