JavaScript/Javascript

프로토타입 (Prototype)

58청춘 2023. 10. 9. 20:43
728x90

정의

자바스크립트의 모든 객체는 자신의 원형(Prototype)이 되는 객체를 가지며 이를 프로토타입이라 한다.

보이지 않는 속성인 [[Prototype]]이 자신의 프로토타입 객체를 참조한다.

이를 __proto__라는 속성으로 참조할 수 있으나 이는 비표준이고 모든 브라우저에서 동작하지 않기에 실사용은 지양하자.

 

.prototype과 [[Prototype]]

모든 객체는 은닉 속성인 [[Prototype]]을 갖는데 특별히 함수 객체는 접근할 수 있는 속성인 prototype을 갖는다.

 

프로토타입이 햇갈리는 이유가 여기서 나온다.

이름이 비슷해 관계를 명확하게 파악하기 쉽지 않다.

[[Prototype]] 이란?

자신의 프로토타입 객체를 참조하는 속성

 

.prototype 이란?

new 연산자로 자신을 생성자 함수로 사용한 경우, 그것으로 만들어진 새로운 객체의                                      [[Prototype]]이 참조하는 값

 

function Func() {}
var a = new Func();

사진에서 constructor는 모든 .prototype객체의 속성에 있는 것으로 실제 객체를 참조한다.

위에서 Func를 가리키는 것이다.

 

Func.prototype의 [[Prototype]]이 Object.prototype으로 연결되는데 이는 모든 객체의 프로토타입 객체로 마지막으로 연결되는 프로토타입 객체이다.

 

정리하자면

  1. new 연산자로 새로운 객체 a를 생성하면, a의 프로토타입 객체는 생성자 함수로 사용한 Func의 속성인 Func.prototype이 된다.
  2. Func.prototype은 constructor 속성을 갖으며, 실제 객체 Func를 가리킨다.
  3. Func.prototype 또한 객체이므로 [[Prototype]]을 갖고있는 모든 객체의 원형이 되는 객체인 Object.prototype을 가리킨다.

 

프로토타입 체인

어떤 객체의 프로퍼티를 참조하거나 값을 할당할 때 해당 객체에 프로퍼티가 없을 경우, 그 객체의 프로토타입 객체를 연쇄적으로 보면서 프로퍼티를 찾는 방식을 프로토타입 체인이라 한다.

 

단, 참조할 때와 값을 할당할 때의 메커니즘이 다르다.

 

프로퍼티를 참조할 때

  1. 찾고자 하는 프로퍼티가 객체에 존재하면 사용한다.
  2. 없으면 [[Prototype]] 링크를 타고 끝까지 올라면서 해당 프로퍼티를 찾는다.
  3. 찾으면 그 값을 사용, 없으면 undefined 반환

 

프로퍼티에 앖을 할당할 때

  1. 찾고자 하는 프로퍼티가 객체에 존재하면 값을 바꾼다.
  2. 프로퍼티가 없고 [[Prototype]] 링크를 타고 올라가서 해당 프로퍼티를 찾았을 경우
    • 그 프로퍼티가 변경가능한 값(writable : true) 라면 새로운 직속 프로퍼티를 할당해 사우이 프로퍼티가 가려지는 현상이 발생
    • 그 프로퍼티가 변경 불가능한 값(writable : false) 라면 비엄격 모드에선 무시되고 엄격 모드에서는 에러 발생
    • 해당 프로퍼티가 세터(setter)인 경우, 이 세터가 호출되고 가려짐이 발생하지 않는다.
가려짐이란? 상위 프로토타입 객체에 동일한 이름의 프로퍼티가 있는 경우, 하위 객체의 프로퍼티에 의해 가려지즌 현상
function Func() {}
Func.prototype.num = 2;
var a = new Func();
a.num = 1;
console.log(a.num); // 1

위의 코드에서 객체 a의 프로토타입 객체인 Func.prototype에 num이 있지만 a.num = 1 로 인해 가려짐 현상이 발생해 1을 출력한다.

 

function Func() {}
Object.defineProperty(Func.prototype, "num", {
  value: 2,
  writable: false
})
var a = new Func();
a.num = 1; // 무시됨
console.log(a.num); // 2

하지만, defineProperty()를 사용하면 변경불가능한 프로퍼티로 만들면 비엄격모드에서 무시되어 2를 출력한다.

 

 

 

참고 링크

 

 

 

 

 

728x90