프로토타입에 대해 설명해주세요
프로토타입은 자바스크립트에서 상속을 지원하기 위한 방법이다.
자바스크립트는 객체들로 구성되어 있는데, 객체는 각각 프로토타입을 가진다.
프로토타입을 통해 자바스크립트의 상속이 구현된다. 객체 간 상속을 구현하는 핵심 메커니즘이다.
ES6에서 Class 문법이 도입되지만, 이는 프로토타입 기반 상속을 문법적으로 감싼 Syntactic Sugar
이다.
객체의 원형이라는 의미 그대로, 상위 객체의 속성이나 메소드를 하위 객체에서 사용할 수 있다.
표현은 삶의 흐름 속에서만 의미를 갖는다
- 현실에 존재하는 것 중 가장 좋은 본보기를 원형(prototype)으로 선택한다.
- 문맥(컨텍스트)에 따라 '범주', 즉 '의미'가 달라진다.
프로토타입 체인
객체에서 어떤 속성이나 메소드에 접근할 때 현재 객체에 찾는 값이 없으면 해당 객체의 상위 프로토타입에서 접근할 값을 찾는 것을 반복한다.
// 프로토타입 체인 예시
function Vehicle(type) {
this.type = type;
}
Vehicle.prototype.getType = function() {
return this.type;
};
function Car(type, brand) {
Vehicle.call(this, type);
this.brand = brand;
}
// 프로토타입 체인 설정
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;
Car.prototype.getBrand = function() {
return this.brand;
};
const myCar = new Car('sedan', 'Toyota');
console.log(myCar.getType()); // 'sedan'
console.log(myCar.getBrand()); // 'Toyota'
프로토타입 기반 OOP 언어의 특징
- 개별 객체(instance) 수준에서 메소드와 변수를 추가
- 객체 생성은 일반적으로 복사를 통해 이루어짐
- 확장(extends)은 클래스가 아니라 위임(delegation)
- 개별 객체 수준에서 객체를 수정하고 발전시키는 능력은 선험적 분류의 필요성을 줄이고 반복적인 프로그래밍 및 디자인 스타일 장려
- 프로토타입 프로그래밍은 일반적으로 분류하지 않고 유사성을 활용하도록 선택
- 결과적으로 설계는 맥락에 의해 평가
어휘적 범위(lexical scope)
변수의 의미는 그 어휘적인(Lexical), 실행 문맥(Execution Context)에서의 의미가 된다
'단어의 의미가 사용되는 근처 환경'에서의 '근처'를 어휘적 범위로 정의한다.
자바스크립트 엔진은 코드가 로드될 때 실행 컨텍스트를 생성하고 그 안에 선언된 변수, 함수를 실행 컨텍스트 최상단으로 호이스팅한다.
this를 어떻게 대할 것인가
단어의 쓰임새가 곧 의미이다.
그것이 어디서 발화되느냐에 따라 단어의 의미가 달라진다.
프로토타입에서는 받아들이는 주체와 문맥이 중요하다.
프로그래밍으로 보면 실행하는 '객체'가 중요하다.
- 메소드: 객체의 함수
- 메시지: 메소드를 실행하라는 메시지 전달
[[Prototype]] vs prototype 프로퍼티
function Person(name) {
this.name = name;
}
var foo = new Person("Lee");
console.dir(Person); // prototype 프로퍼티 있음
console.dir(foo); // prototype 프로퍼티 없음
[[Prototype]]
함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯이다.
객체의 입장에서 자신의 부모 역할을 하는 프로토타입 객체를 가리킨다.
console.log(Person.__proto__ === Function.prototype); // true
__proto__
접근자는 deprecated
가 되어 Object.getPrototypeOf()
/ Object.setPrototypeOf()
사용을 추천한다.
console.log(foo.__proto__ === Object.getPrototypeOf(foo)) // true
console.log(Person.__proto__ === Object.getPrototypeOf(Person)) // true
Object.create()
는 [[Prototype]]
이 proto
를 참조하는 빈 객체를 만들어준다.
Object.create
를 사용하면 for..in
을 사용해 프로퍼티를 복사하는 것보다 더 효과적으로 객체를 복제할 수 있다.
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
Object.create(null)
을 사용하면 프로토타입이 없는 객체를 만들 수 있다.
ob
의 모든 프로퍼티를 포함한 완벽한 사본 생성이 가능하다.
prototype 프로퍼티
함수 객체만 가지고 있는 프로퍼티이다.
함수 객체가 생성자로 사용될 때 이 함수를 통해 생성될 객체의 부모 역할을 하는 객체(프로토타입 객체)를 가리킨다.
console.log(Person.prototype === foo.__proto__); // true
키워드 정리
- 문맥(context)
- 프로토타입 체인