[[prototype]]과 proto 의 차이를 알아보겠습니다. 자바스크립트에서는 객체의 숨김 프로퍼티로 [[prototype]]를 가지고 있습니다. 어떤 프로퍼티를 찾으려고 할때 만약 객체에 이 프로퍼티가 존재하지 않는다면 [[prototype]] 프로퍼티가 참조하는 다른 객체에서 이를 찾으려고 시도합니다. 여기서 이 객체를 바로 프로토타입이라고 합니다.
proto 을 요즘엔 잘 쓰지 않는다고 합니다. 요즘엔 보통 Object.getPrototypeOf나 Object.setPrototypeOf 메서드를 활용합니다.
그럼 proto 는 뭘까요? proto 는 [[prototype]]의 getter이자 setter입니다. getter와 setter는 마치 프로퍼티처럼 사용할 수가 있습니다.
this는 prototype에 영향을 받지않습니다. this는 알고 있듯이 메서드를 호출하는 런타임에서의 객체를 의미하죠. 코드를 확인해봅시다.
const animal = {
eats: true,
setName() {
this.name = "seunghwan";
},
};
const rabbit = {
jumps: true,
__proto__: animal,
};
rabbit.setName();
console.log(animal); // { eats: true, setName: [Function: setName] }
console.log(rabbit); // { jumps: true, name: 'seunghwan' }
위 코드를 보면 알 수 있듯이 this는 무조건 .
앞의 객체를 의미합니다.
for...in문을 사용해 객체의 프로퍼티를 출력하면 객체의 프로퍼티뿐만 아니라 프로토타입의 프로퍼티도 출력이됩니다. 따라서 Object.prototype.hasOwnProperty 메서드를 활용하면 걸러낼 수 있습니다.
// for...in문은 prototype의 프로퍼티도 순회대상에 포함합니다.
const animal = {
eats: true,
};
const rabbit = {
jumps: true,
__proto__: animal,
};
console.log(Object.keys(rabbit)); // jump만 반환
for (const property in rabbit) {
console.log(property); // jumps, eats
}
// prototype의 프로퍼티를 걸러내기 위해서 obj.hasOwnProperty 메서드를 활용합니다.
for (const property in rabbit) {
if (rabbit.hasOwnProperty(property)) {
console.log("자신의 프로퍼티:", property); // jumps
} else {
console.log("상속 프로퍼티:", property); // eats
}
}
그렇다면 왜 hasOwnProperty는 출력되지 않을까요? 그건 객체의 플래그 중에 enumerable이 false로 설정되어 있기 때문입니다. 이렇게 enumerable이 false로 설정되어 있는 대표적인 메서드들은 다음과 같습니다.
모던 자바스크립트에서는 프로토타입에 관한 메서드들이 추가됐습니다.
[[prototype]]의 getter이자, setter인 proto를 활용하는 것 대신에 Object 생성자 함수의 메서드를 사용하세요.
proto를 사용해 [[prototype]]을 변경하는 것은 객체 프로퍼티 접근 최적화 알고리즘을 망치게 됩니다. 따라서 자바스크립트에서는 객체를 초기에 생성할때만 프로토타입을 설정하도록 권고하고 있습니다.
제가 지금까지 알고있는 객체를 복사하는 방법은 2가지 입니다.
여기서 한 가지 방법을 더 알게되네요.
const obj = Object.create(
Object.getPrototypeOf(target),
Object.getOwnPropertyDescriptors(target) // getOwnPropertyDescriptor와 헷갈리기ㄴㄴ
);`
프로토타입을 가지지 않는 객체를 단순객체(pure dictionary)라고 합니다.
const obj = Object.create(null);
이 객체는 프로토타입을 가지지 않기 때문에 내장메서드를 활용할 수 없습니다.
지금까지 자바스크립트의 프로토타입을 알아봤습니다. 객체, 생성자함수 뿐만아니라 이후에 배울 클래스도 프로토타입을 기반으로 상속을 구현합니다. 이는 뒤에서 자세히 알아보겠습니다.