자바스크립트는 객체 기반의 프로그래밍 언어이며 자바스크립트를 이루고 있는 거의 " 모든 것" 이 객체다.
객체는 상태 데이터와 동작을 하나의 논리적인 단위로 묶은 복합적인 자료구조라고 할 수 있다. 이때 객체의 상태 데이터를 프로퍼티, 동작을 메서드라 부른다.
상속 : 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다.
자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.
function Circle(radius){
this.radius = radius;
this.getArea = function(){
return Math.PI * this.radius ** 2;
}
}
const circle1 = new circle(1);
const circle2 = new Circle(2);
위의 코드를 보면 Circle 생성자 함수가 생성하는 모든 객체는 프로퍼티와 메서드를 갖는다.
자바스크립트는 프로토타입을 기반으로 상속을 구현한다.
function Circle(radius){
this.radius = radius;
}
// Circle 생성자 함수가 생성한 모든 인스턴스가 getArea 메서드를
// 공유해서 사용할 수 있도록 프로토타입에 추가한다.
// 프로토타입은 Circle 생성자 함수의 Prototype 프로퍼티에 바인딩되어있다.
Circle.prototype.getArea = function(){
return Math.PI * this.radius **2;
}
const Circle1 = new Circle(1);
//Circle 생성자 함수가 생성한 모든 인스턴스는 부모객체의 역할을 하는
//프로토타입 Circle.prototype으로부터 getArea 메서드를 상속받는다.
프로토타입은 어떤 객체의 부모객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티를 제공한다.
모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조다. [[Prototype]]에 저장되는 프로토타입은 객체 생성방식에 의해 결정된다. 즉, 객체가 생성될때 객체 생성방식에 따라 프로토타입이 결정되고 [[Prototype]]에 저장된다.
객체와 프로토타입과 생성자 함수는 서로 연결되어 있다.
proto 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 자신의 [[Prototype]] 내부 슬롯이 가리키는 프로토타입에 간접적으로 접근할 수 있다.
그리고 프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있고, 생성자 함수는 자신의 prototype 프로퍼티를 통해 프로토타입에 접근할 수 있다.
모든 객체는 proto 접근자 프로퍼티를 통해 자신의 프로토타입 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근 할 수 있다.
proto 접근자 프로퍼티는 객체가 직접 소유하는 프로퍼티가 아니라 Object.prototype의 프로퍼티다. 모든 객체는 상속을 통해 Object.prototype.proto 접근자 프로퍼티를 사용할 수 있다.
const person = {name : "Lee"};
console.log(person.hasOwnProperty("__proto__")); // false
console.log(Object.getOwnPropertyDescriptor(Object.prototype,"__proto__"); //{get:f,set:f,enumerable:false, configurable:ture}
console.log({}.__proto__ === Object.prototype); // true
[[Prototype]] 내부 슬롯의 값, 즉 프로토타입에 접근하기 위해 접근자 프로퍼티를 사용하는 이유는 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서다.
const parent ={}; const child = {}; child.__proto__ = parent; parent.__proto__ = child; // 오류 발생 //프로토타입 체인은 단방향 링크드 리스트로 구현되야 한다.
코드 내에서 proto접근자 프로퍼티를 직접사용하는 것은 권장하지 않는다.
모든 객체가 proto 접근자 프로퍼티를 사용할 수 있는 것은 아니기 때문이다.
예를 들어
const obj = Object.create(null);
obj는 프로토타입 체인의 종점이다. 따라서 Object.proto를 상속 못받는다.