자바스크립트는 프로토타입 기반 언어이다. 클래스 기반 언어에서는 '상속'을 사용하지만 프로토타입 기반의 언어에서는 어떤 객체를 원형으로 삼고 이를 복제(참조)함으로써 상속과 비슷한 효과를 얻는다.
💡 let instance = new Constructor();
new
연산자와 함께 호출하면__proto__
라는 프로퍼티가 자동으로 부여되는데prototype은 객체인데, 이 내부에는 인스턴스가 사용할 메서드를 저장한다.
그러면 인스턴스에서도 숨겨진 프로퍼티인 __proto__
를 통해 메서드들에 접근할 수 있게 된다.
예를들어 Person이라는 생성자 함수의 prototype에 getName이라는 메서드를 지정하면 Person의 인스턴스는 __proto__
프로퍼티를 통해 getName을 호출할 수 있다.
var Person = function(name){
this._name = name;
}
Person.prototype.getName = function(){
return this._name;
}
console.dir(Person.prototype)
/*
[object Object] {
⭐️ getName: function(){
return this._name;
}
} */
var jinkyung = new Person('jinkyung')
console.log(jinkyung.getName()) //jinkyung
console.log(Person.prototype === jinkyung.__proto__) //true
instance의 __proto__
가 Constuctor의 prototype 프로퍼티를 참조하므로 결국 둘은 같은 객체를 바라보기 때문이다. 즉, instance의 생략 가능한 프로퍼티인 __proto__
는 Constuctor의 prototype을 참조한다.
new
연산자를 사용해 호출할 경우__proto__
가 자동으로 생성되며__proto__
는 생략 가능하고💡 메서드 오버라이드 : 메서드 위에 메서드를 덮어씌웠다는 표현, 원본을 제거하고 다른 대상으로 교체하는 것이 아니라 원본이 그대로 있는 상태에서 다른 대상을 그 위에 얹는 것
var Person = function(name){
this.name = name;
}
Person.prototype.getName = function(){
return this._name;
}
var iu = new Person('지금');
iu.getName = function(){
return '바로 ' + this.name;
}
console.log(iu.getName())
자바스크립트 엔진이 getName
이라는 메서드를 찾는 방식은 가장 가까운 대상인 자신의 프로퍼티를 검색하고, 없으면 그다음으로 가까운 대상인__proto__
를 검색하는 순서로 진행된다.
어떤 데이터의 __proto__
프로퍼티 내부에 다시 __proto__
프로퍼티가 연쇄적으로 이어진 것은 프로토타입 체인이라 하고, 이 체인을 따라가며 검색하는 것을 프로토타입 체이닝이라고 한다.
여러 개의 객체를 하나의 객체의 프로토타입으로 설정하여 다중 프로토타입 체인을 만들 수 있습니다. 이는 다중 상속과 유사한 효과를 제공한다.
자바스크립트의 기본 내장 데이터 타입들은 모두 프로토타입 체인이 1단계나 2단계로 끝나는 경우만 있었지만 사용자가 새롭게 만드는 경우 그 이상도 가능하다.
대각선의 __proto__
를 연결해 나가기만 하면 무한대로 체인 관계를 이어나갈 수 있다.
대각선의 __proto__
를 연결하는 방법은 __proto__
가 가리키는 대상, 즉 생성자 함수의 prototype이 연결하고자 하는 상위 생성자 함수의 인스턴스를 바라보게끔 해주면 된다.