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에게 해당하는 것이다.
- new연산자로 새로운 객체 a를 생성하였으므로, a의 프로토타입 객체는 생성자 함수로 사용한 Test 의 속성인 Test.prototype이 된다.
- Test.prototype 은 constructor속성을 가지며 실제 객체 Test을 가리킨다.
- 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 |