프로토타입 개념
- 자바스크립트는 프로토타입을 기반으로 상속을 구현 -> 코드 재사용에 용이
- 생성자 함수는 동일한 프로퍼티(메서드 포함) 구조를 갖는 객체를 여러 개 생성할 때 유용
- 생성자 함수에서 this로 할당된 프로퍼티,메서드는 인스턴스가 생성될때 할당된다.
// 아래 Circle 생성자 함수의 getArea는 모든 인스턴스가 가지는 메서드 이므로 메모리 낭비가 됨
function Circle(radius) {
this.radius = radius;
this.getArea = function () {
return Math.PI * this.radius ** 2;
}
}
// 프로토타입을 이용한 getArea 중복 제거
// 모든 인스턴스는 getArea 메서드를 공유함
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getArea = function () {
return Math.PI * this.radius ** 2;
}
- 모든 객체는 [[[Prototype]] 이라는 내부 슬롯을 가진다
- 내부 슬롯의 값은 프로토타입의 참조값이다. -> 객체 생성 방식에 따라 결정됨
- 내부 슬롯에는 직접 접근할 수 없다 (__proto__ 접근자 프로퍼티로 간접적으로 접근 가능)
- __proto__ 는 프로토타입 상속을 통해 사용된다 (Object.prototype 의 프로퍼티이다.)
- 프로토타입의 참조( [[Prototype]] 내부슬롯 ) 에 의해 프로토타입 체인이 이루어진다
- 프로토타입 체인은 단방향 링크드 리스트이다. (내부슬롯을 직접 참조할 수 없는 이유)
prototype, constructor, 객체 의 관계
- 모든 객체는 하나의 프로토타입을 갖는다, 모든 프로토타입은 생성자 함수와 연결되어 있다
- 함수 객체의 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
- non-constructor(화살표 함수, ES6 축약 표현 메서드) 는 프로토타입을 생성X, prototype 프로퍼티 X
- 객체의 __proto__ 와 함수의 prototype은 동일한 프로토타입을 가리킨다.
- 모든 prototype은 constructor를 갖는다. (자신을 참조하고 있는 생성자 함수를 가리킴)
function Person(name) {
this.name = name;
}
const me = new Person('KIM');
console.log(Person.prototype === me.__proto__); // true
console.log(me.constructor === Person); // true
객체 생성 방식에 따른 프로토타입의 결정
1. 객체 리터럴
const obj = { x: 1 };
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty('x')); // true
2. Object 생성자 함수
const obj = new Object();
obj.x = 1;
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty('x')); // true
3. 생성자 함수
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hi My name is ${this.name}`);
}
const me = new Person('Lee');
const you = new Person('Kim');
me.sayHello(); // Hi My name is Lee
you.sayHello(); // Hi My name is Kim
4. Object.create 메서드
// 명시적으로 프로토타입을 지정함
// 1. Object.prototype을 상속받지 못함
let obj = Object.create(null);
console.log(Object.getPrototypeOf(obj) === null); // true
console.log(obj.toString()); // TypeError
// 2. Object.prototype을 프로토타입으로 지정
// 객체 리터럴 생성 방식과 같음
obj = Object.create(Objet.prototype);
console.log(Object.getPrototypeOf(obj) === Object.prototype);
// 3. 임의의 객체를 직접 상속
// (1) 객체 리터럴
const myProto = { x:10 };
obj = Object.create(myProto);
console.log(obj.x); // 10
// (2) 생성자 함수
function Person(name) {
this.name = name;
}
// obj = new Person('Lee'); 와 동일함
obj = Object.create(Person.prototype);
obj.name = 'Lee';
5. 클래스(ES6)
프로토타입 체인
- 객체의 프로퍼티에 접근할 때 해당 객체에 접근하려는 프로퍼티가 없다면 [[Prototype]] 내부 슬롯의 참조를 따라 부모 프로토타입의 프로퍼티를 순차적으로 검색
- 프로토타입 체인은 상속과 프로퍼티 검색을 위한 매커니즘이다.
- 스코프 체인과 프로토타입 체인은 서로 협력하여 식별자와 프로퍼티를 검색한다. (아래 me.hasOwnProperty('name'); 참고)
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hi My name is ${this.name}`);
}
const me = new Person('Lee');
// hasOwnProperty는 Object.prototype의 메서드
// me 객체가 Person.prototype 뿐만 아닌 Object.prototype도 상속 받았다는 것
// 스코프에서 me 식별자 검색 -> me 객체의 프로토타입 체인에서 프로퍼티(메서드) hasOwnProperty 검색
console.log(me.hasOwnProperty('name'); // true
// 프로토타입 체인
Object.getPrototypeOf(me) === Person.prototype // true
Object.getPrototypeOf(Person.prototype) === Object.prototype // true
'FE > Javascript' 카테고리의 다른 글
[Javascript] this 복습 (2) | 2025.08.04 |
---|---|
13. 모던 자바스크립트 Deep Dive(스코프) (0) | 2024.12.08 |
12. 모던 자바스크립트 Deep Dive(함수) (0) | 2024.12.07 |
11. 모던 자바스크립트 Deep Dive(원시 값과 객체의 비교) (0) | 2024.12.06 |
10. 모던 자바스크립트 Deep Dive (객체 리터럴) (0) | 2024.12.05 |