관리 메뉴

bright jazz music

프로토타입 prototype (1) : __proto__ 접근자 프로퍼티 본문

Language/Javascript

프로토타입 prototype (1) : __proto__ 접근자 프로퍼티

bright jazz music 2025. 5. 6. 20:49

프로토타입 객체 또는 프로토타입은 객체 간 상속을 구현하기 위해 사용된다. 프로토 타입은 어떤 객체의 상위, 즉 부모 객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티와 메서드를 를 제공한다. 프로토타입을 상속 받은 하위 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 사용할 수 있다.

 

모든 객체는 [[property]] 라는 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조이다. null인 경우도 있다. [[Prototype]] 슬롯에 저장되는 프로토타입은 객체 생성 방식에 의해 결정된다. 즉, 객체가 생성될 때 객체 생성 방식에 따라 프로토타입이 결정되고 [[Prototype]] 슬롯에 저장된다.

 

예를 들어 객체 리터럴에 의해 생성된 객체의 프로토타입은 Object.prototype이고 생성자 함수에 의해 생성된 객체의 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩 되어 있는 객체다.

 

예를 들어 const person = { name: 'cha'} 라고 선언했다면, 그 프로토타입은 Object.prototype이 된다.

 

모든 개체는 하나의 프로토타입을 갖는다. 그리고 모든 프로토타입은 생성자 함수와 연결돼 있다. 즉 객체와 프로토타입은 생성자 함수와 연결돼 있다.

 

[Prototype]] 내부 슬롯에는 직접 접근할 수 없지만,  __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 자신의 [[prototype]] 내부 슬롯이 가리키는 프로토타입에 간접적으로 접근할 수 있다. 그리고 프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있고 생성자 함수는 자신의 prototype 프로퍼티를 통해 프로토타입에 접근할 수 있다.

 

즉, 모든 객체는 __proto__ 접근자 프로퍼티를 통해 프로토타입을 가리키는 [[prototype]] 내부 슬롯에 접근할 수 있다.

 

---

 

__prototype__ 접근자 프로퍼티

 

내부 슬롯은 프로퍼티가 아니다. 따라서 자바스크립트는 원칙적으로 내부 메서드에 직접적으로 접근하거나 호출할 수 있는 방법을 제공하지 않는다. 단, 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공한다. 위에서도 언급했듯이 __proto__ 접근자를 사용해 간접적으로 내부 슬롯인 [[Prototype]]에 접근하여 그 안에 들어 있는 값인 프로토타입에 접근할 수 있다.

 

접근자 프로퍼티인 __proto__(Object.는 그 자체로는 값을 갖지 않는다. 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용되는 접근자 함수, 즉 [[Get]], [[Set]] 프로퍼티 어트리뷰트로 구성되어 있다.

Object.prototype의 접근자 프로퍼티인 __proto__는 getter/setter 함수라고 부르는 접근자 함수를 통해 내부 슬롯의 값인 프로퍼티를 취득하거나 할당한다. 따라서 __proto__를 통해 프로토타입에 접근한다면, 내부적으로는 __proto__가 가진 get함수(get __proto__)를 사용하는 것이다. 새로운 프로토타입을 할당할 때에는 __proto__가 가진 setter함수(set __proto_)를 사용한다.

 

const obj = {};
const parent = {x:1}

//getter(get __proto__) 사용gkdu obj 객체의 프로토타입을 가져온 상태
obj.__proto__;

//setter(set __proto__) 사용하여 새로운 값을 할당
obj.__proto__ = parent; 

console.log(obj.x); // 1

 

 

__proto__ 접근자 프로퍼티는 상속을 통해 사용된다.

__proto__ 접근자 프로퍼티는 객체가 직접 소유하는 프로퍼티가 아니라 Object.prototype의 프로퍼티다. 모든 객체는 상속을 통해 Object.prototype.__proto__ 접근자 프로퍼티를 사용할 수 있다.

 

Object.prototype

모든 객체는 프로토타입의 계층 구조인 프로토타입 체인(prototype chain)에 묶여있다.  자바스크립트 엔진은 객체의 프로퍼티와 메서드에 접근하려고 할 때, 해당 객체에 접근하려는 프로퍼티가 존재하지 않는다면, __proto__ 접근자 프로퍼티가 가리키는 참조를 따라 자신의 부모역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 프로토타입 체인의 종점, 즉 프로토타입 체인의 최상위 객체는 Object.prototype이며 이 객체의 프로퍼티와 메서드는 모든 객체에 상속된다.

 

 

__proto__ 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유: 순환참조를 막기 위해서

[[Prototype]] 내부 슬롯의 값, 즉 프로토타입에 접근하기 위해 접근자 프로퍼티를 사용하는 이유는 상호 참조에 의해 프로토타입 체인이 새성되는 것을 방지하기 위해서이다. 이를 지키기 위해 프로토타입 체인은 단방향 링크트 리스트로 구현되어야 한다. 만약 __proto__ 접근자를 사용하지 않고도 프로토타입을 교체할 수 있다면 무한루프 발생 가능성이 높아진다. 

const parent = {};
const child = {};

// child 프로토타입을 parent로 설정
child.__proto__ = parent;

// parent 의 프로토타입을 child로 설정
parent.__proto__ = child; // 순환참조 에러 발생.

 

 

 

__proto__ 접근자 프로퍼티를 코드 내에서 사용하는 것은 권장되지 않는다.

모든 객체가 __proto__프로퍼티를 사용할 수 있는 것은 아니기 때문이다. Object.prototype을 상속받지 않는 객체를 생성할 수도 있기 때문에 __proto__ 접근자 프로퍼티를 사용할 수 없는 경우기 발생한다. 따라서 __proto__ 접근자 프로퍼티 대신 아래 메서드를 사용하는 것이 권장된다.

 

- Object.getPrototypeOf : 프로토타입의 참조를 취득하려는 경우

- Object.setPrototypeOf : 프로토타입을 교체하려는 경우

 

// Object.__proto__를 상속받지 못하는 경우
const obj = Object.create(null);

console.log(obj.__proto__) // undefined

console.log(Object.getPrototypeOf(obj)); // null

 

const ob = {};
const parent = { x:1 };

Object.getPrototypeOf(obj); // obj.__proto__

Object.setPrototypeOf(obj, parent); // obj.__proto__ = parent ; 

console.log(obj.x); // 1
Comments