본문 바로가기

프론트엔드

Prototype 프로토타입

Prototype 프로토타입


javascript의 모든 객체는 자신의 원형이 되는 객체를 가진다. 이를 프로토 타입이라고 한다.
보이지 않는 속성이 [[Prototype]] 이 자신의 프로토타입 객체를 참조한다. 이를 __proto__ 라는 속성으로 참조할 수 있지만 비표준이고 모든 브라우저에서 동작하는 것은 아니기 때문에 실제로 사용하는 것은 피해야한다.

 

 

.prototype 과 [[Prototype]]


위에 말했듯이 모든 객체는 은닉 객체인 [[Prototype]] 을 갖는다. 그리고 함수 객체는 접근할 수 있는 속성인 .prototype 을 갖는다. 이름만 보면 같은것으로 보이기 때문에 관계를 명확히 파악하여야한다.

  • [[Prototype]] : 자신의 프로토타입 객체를 참조하는 속성이다.
  • .prototype : new 연산자로 자신을 생성자 함수로 사용한 경우, 그걸로 만들어진 새로운 객체의 [[Prototype]] 이 참조하는 값이다.
class Test {
    constructor() {}
    a = 1
}

var a = new Test; // Test를 생성자로 호출하여 
새로운 객체 a를 생성

 

위 이미지를 보면 쉽게 이해가 된다. new연산자로 생성한 a는 새로운 객체가 되었으므로 Test의 prototype을 가지게 된다. 이것이 .prototype이고, [[prototype]]은 자신의 프로토 타입 객체이므로 Test에게 해당하는 것이다.

 

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

 

프로토타입 체인


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

function Func() {}
Func.prototype.num = 2;

var a = new Func();
a.num = 99; //가려짐 발생

console.log(a.num); // 99 
function Func() {}
Object.defineProperty(Func.prototype, 'num', {
	value: 2,
	writable: false,  //변경 불가능한 값 설정
})

var b = new Func();
b.num = 77; //무시됨

console.log(b.num); //2
  • 프로퍼티를 참조할때
    • 찾고자 하는 프로퍼티가 객체에 존재하면 사용한다.
    • 없으면 [[Prototype]] 링크를 타고 끝까지 올라가면서 해당 프로퍼티를 찾는다.
    • 찾으면 그 값을 사용하고 없으면 undefined를 반환한다.
  • 프로퍼티에 값을 할당할때
    • 찾고자 하는 프로퍼티가 객체에 존재하면 값을 바꾼다.
    • 없으면 [[Prototype]] 링크를 타고 끝까지 올라가면서 해당 프로퍼티를 찾는다.
    • 찾았을경우, 3가지로 나뉘어진다.
      • 그 프로퍼티가 변경 가능한 값이라면 그 값을 덮어쓴다. (가려진다)
      • 그 프로퍼티가 변경 불가능한 값이라면 무시되거나 에러가 발생한다. (엄격모드에서 에러 발생, 비엄격모드에서는 무시)
      • 해당 프로퍼티가 setter 일 경우, 이 setter가 호출되고 덮어씌워지지 않는다. (가려지지 않는다.)

 


Object.create() 참고~! prototype이 사라짐 !

var a = Object.create(null);
a.name = 'joanna';

위의 코드를 넣고 a를 찍어보면 위 이미지와 같이 나온다. 자세히 보면 prototype이 없는 것을 알 수 있다. Object.create()는 프로토타입 객체를 받아 연결시켜 새 객체를 만드는 함수로, 프로토 타입 객체를 바꾸기 때문에 원래의 constructor를 잃어버린다.

 


instanceof, isPrototypeOf

 

function a () {}
function b () {}

b.prototype = new a();
b.prototype.constructor = b;

function c () {}

c.prototype = new b();
c.prototype.constructor = c;

var d = new c();

console.log(d instanceof a, a.prototype.isPrototypeOf(d)); // true
console.log(d instanceof b, b.prototype.isPrototypeOf(d)); // true
console.log(d instanceof c, c.prototype.isPrototypeOf(d)); // true

특정 객체의 프로토타입 체인에 찾고자 하는 객체가 있는지 검사할 때 사용된다.

 


getPrototypeOf, setPrototypeOf

function a () {}
function b () {}

var b = new a(); 
console.log(Object.getPrototypeOf(a)); //a.prototype //가져오기

Object.setPrototypeOf(a, b.prototype); //b로 할당
console.log(Object.getPrototypeOf(a)); //b.prototype

각각 특정 객체의 프로토타입 객체를 가져오고 할당하는 함수이다.

반응형

'프론트엔드' 카테고리의 다른 글

React vs Vue  (0) 2022.11.17
hasOwnProperty & hasOwn & (key) in 차이점  (0) 2022.11.04
new 연산자  (0) 2022.11.04
Closure 클로져  (0) 2022.11.04
Hoisting 호이스팅  (0) 2022.11.02