프로토타입 체인이란?
const a = {};
a.
빈 Object literal notation
으로 a
를 정의한 뒤에 a.
을 콘솔에 입력하면, 아래 이미지와 같이 많은 프로퍼티 후보군이 나온다. 이 때 후보군이 나오는 이유가 바로 프로토타입 체인 때문이다.
우리는 분명 프로퍼티를 정의한 적이 없는데, 정의한적도 없는 프로퍼티를 이용할 수 있는 이유가 바로 프로토타입 체인이다.
__defineGetter__
__defineSetter__
__lookupGetter__
__lookupSetter__
__proto__
city
constructor
greet
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toLocaleString
toString
valueOf
만일 우리가 a.toString()
이라는 코드를 입력하면, 메서드를 정의한적이 없음에도 에러가 나지 않는다.
a.toString(); // "[object Object]"
toString()
은 비록 본래의 목적대로 동작하진 않지만, 동작은 한다. 아래 코드처럼 Object.getPrototypeOf()
를 사용하면 프로토타입을 얻어볼 수 있다.
이전에는
a.__proto__
와 같은 방식으로 프로토 타입에 접근했으나, 추후에는 웹 표준에서 사라질 문법이다.
Object.getPrototypeOf(a);
/*
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
*/
- 프로토타입 체인은 객체지향언어의 상속과 비슷하다.
- 코드에서 오브젝트에 딸린 프로퍼티를 찾으려 할 때, 자바스크립트는 내부적으로 다음과 같은 과정을 거친다.
- 현재 오브젝트에 해당 프로퍼티가 존재하는지 확인한다.
- 없다면? 해당 오브젝트의 프로토타입에 해당 프로퍼티가 존재하는지 확인한다.
- 없다면? 상위 오브젝트의 프로토타입에 또 해당 프로퍼티가 존재하는지 확인한다.
- 프로토타입을 끝까지 뒤져봤는데 없다면
undefined
를 반환한다.
예제 코드로 살펴보면 아래와 같다.
// 테스트용 프로토타입 오브젝트 정의
const testPrototype = {
a: 10,
};
// testPrototype 을 프로토타입으로 하는 객체 생성
const testObject = Object.create(testPrototype);
// 객체에 아무런 프로퍼티도 정의되어 있지 않음
testObject; // {}
// 프로퍼티 'a' 를 찾으면, 프로토타입 체인을 돌며 testPrototype 에 있는 '10' 이라는 값을 찾아냄
testObject.a; // 10
// 프로퍼티 'a' 에 200 이라는 값을 설정함
testObject.a = 200;
// 이제 'a' 라는 값은 프로퍼티에 있으므로, 프로토타입 체인을 돌지 않아도 바로 찾을 수 있음
testObject.a; // 200
// 'a' 라는 프로퍼티를 삭제함
delete testObject.a; // true
// 'a' 라는 프로퍼티를 다시 찾으면, 이제는 없어서 다시 프로토타입 체인에 접근하게 되고 프로토타입에 있는 10이라는 값을 반환함
testObject.a; // 10
testObject.a
라는 프로퍼티에 접근하면,
testObject 프로퍼티
->testObject 프로토타입
->Object 프로토타입
순으로 찾게 된다.- 프로토타입은 상위 타입의 프로토타입을 가리킨다. 그래서 결국 마지막에는 최상위인
Object 프로토타입
을 뒤지게 된다.
Shadowing properties
란?
const myDate = new Date(1995, 11, 17);
console.log(myDate.getYear()); // 95
myDate.getYear = function () {
console.log("something else!");
};
myDate.getYear(); // 'something else!'
이렇게 프로토타입에 존재하는 함수를 굳이 프로퍼티로 덧씌우는 행위를 Shadowing properties
라고 한다.
이전 코드 예제에서도 Shadowing properties
가 등장했다.
특정 프로토타입을 가진 오브젝트를 생성하고 싶다면?
Object.create()
이용하기
const personPrototype = {
greet() {
console.log("hello!");
},
};
const carl = Object.create(personPrototype);
carl.greet(); // hello!
프로토타입이 될 오브젝트를 먼저 정의한 뒤에 Object.create()
로 오브젝트를 생성하면, 해당 프로토타입을 가진 오브젝트가 생성된다.
생성자 이용하기
const personPrototype = {
greet() {
console.log(`hello, my name is ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// or
// Person.prototype.greet = personPrototype.greet;
const reuben = new Person("Reuben");
reuben.greet(); // hello, my name is Reuben!
프로토타입인지 프로퍼티인지 확인하는 메서드
Object.hasOwnProperty()
peter.hasOwnProperty("greet"); // false -> 프로토타입임
peter.hasOwnProperty("name"); // true -> 프로퍼티임
Object.hasOwn()
Object.hasOwn(peter, "name"); // true
Object.hasOwn(peter, "greet"); // false
프로토타입이 존재하는 이유
자바의 상속의 존재 이유와 같다. 프로토타입 오브젝트에 정의해둔 메서드나 프로퍼티를 재사용하고 싶은 것이다.
const personPrototype = {
greet() {
console.log(`hello, my name is ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
function Professor(name, lecture) {
this.lecture = lecture;
this.name = name;
}
Object.assign(Professor.prototype, Person.prototype);
const sammy = new Professor("sammy", "math");
sammy.greet(); // hello, my name is sammy!
function Student(name, age) {
this.name = name;
this.age = age;
}
const musk = new Student("musk", 50);
Object.assign(Student.prototype, Person.prototype);
musk.greet(); // hello, my name is musk!
Person
의 프로토타입을 상속받아Student
와Professor
를 만들 수 있었다.
레퍼런스
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes
'자바스크립트 > 인터뷰' 카테고리의 다른 글
var 의 문제점을 짚어보고 let, const 와 비교해보세요. (0) | 2022.12.17 |
---|---|
array slice 메서드에 대해서 설명해보세요. (0) | 2022.12.17 |
JSON 오브젝트에 대해서 설명해보세요. (0) | 2022.12.17 |
call, apply, bind 의 차이를 말해보세요. (0) | 2022.12.17 |
JS 에서 오브젝트를 만드는 방법을 아는대로 말해보세요. (0) | 2022.12.16 |