TIL_20210327
프로토타입 상속
- 자바스크립트의 객체는 명세서에서 명명한
[[Prototype]]
이라는 숨김 프로퍼티가 존재. 이 숨김 프로퍼티 값은null
이거나 다른 객체에 대한 참조가되는데, 다른 객체를 참조하는 경우 참조 대상을 '프로토타입(prototype)'이라 함 oject
에서 프로퍼티를 읽으려고 하는데 해당 프로퍼티가 없으면 자바스크립트는 자동으로 프로토타입에서 프로퍼티를 탐색. 이러한 동작 방식을 '프로토타입 상속'이라 함
let animal = {
eats: true
walk() {
alert("동물이 걷습니다.");
}
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal;
alert( rabbit.jumps ); // true
alert( rabbit.eats ); // true
rabbit.walk(); // 동물이 걷습니다.
__proto__
는[[Prototype]]
의 getter(획득자)이자 setter(설정자)- 객체
rabbit
에서 프로퍼티를 얻고싶은데 해당 프로퍼티가 없다면, 자바스크립트는 자동으로animal
이라는 객체에서 프로퍼티를 탐색 rabbit
의 프로토타입은animal
/rabbit
은animal
을 상속 /eats
는 "상속 프로퍼티(inherited property)"
let animal = {
eats: true,
walk() {
/* rabbit은 이제 이 메서드를 사용하지 않습니다. */
}
};
let rabbit = {
__proto__: animal
};
rabbit.walk = function() {
alert("토끼가 깡충깡충 뜁니다.");
}; // 객체 rabbit에 메서드 walk를 직접 할당
rabbit.walk(); // 토끼가 깡충깡충 뜁니다.
- 프로토타입은 프로퍼티를 읽을 때만 사용
- 프로퍼티를 추가, 수정하거나 지우는 연산은 객체에 직접
rabbit.walk()
를 호출하면 프로토타입에 있는 메서드가 실행되지 않고, 객체rabbit
에 추가한 메서드가 실행
- 접근자 프로퍼티(accessor property)는 setter 함수를 통해서 프로퍼티에 값을 할당하므로 이 규칙이 적용되지 않음. 접근자 프로퍼티에 값을 할당하는 것은 함수를 호출하는 것과 같기 때문
let user = {
name: "John",
surname: "Smith",
set fullName(value) {
[this.name, this.surname] = value.split(" ");
},
get fullName() {
return `${this.name} ${this.surname}`;
}
};
let admin = {
__proto__: user,
isAdmin: true
};
alert(admin.fullName); // John Smith (*)
admin.fullName = "Alice Cooper"; // (**)
alert(admin.fullName); // Alice Cooper (state of admin modified)
alert(user.fullName); // John Smith (state of user protected)
(*)
로 표시한 줄에서admin.fullName
은 프로토타입(user
)에 있는 getter 함수(get fullName
)를 호출하고,(**)
로 표시한 줄의 할당 연산은 프로토타입에 있는 setter 함수(set fullName
)를 호출
let animal = {
walk() {
if (!this.isSleeping) {
alert(`동물이 걸어갑니다.`);
}
},
sleep() {
this.isSleeping = true;
}
};
let rabbit = {
name: "하얀 토끼",
__proto__: animal
};
// rabbit의 프로퍼티 isSleeping을 true로 변경
rabbit.sleep();
alert(rabbit.isSleeping); // true
alert(animal.isSleeping); // undefined (프로토타입에는 isSleeping이라는 프로퍼티가 없음)
this
는 프로토타입에 영향을 받지 않음- 메서드를 객체에서 호출했든 프로토타입에서 호출했든 상관없이
this
는 언제나.
앞에 있는 객체 this
에 데이터를 쓰면animal
이 아닌 해당 객체의 상태가 변화- 메서드는 공유되지만, 객체의 상태는 공유되지 않는다고 결론
프로토타입 체이닝
let animal = {
eats: true,
walk() {
alert("동물이 걷습니다.");
}
};
let rabbit = {
jumps: true,
__proto__: animal
};
let longEar = {
earLength: 10,
__proto__: rabbit
};
longEar.walk(); // 동물이 걷습니다.
alert(longEar.jumps); // true
- 순환 참조(circular reference)는 비허용.
__proto__
를 이용해 닫힌 형태로 다른 객체를 참조하면 에러가 발생 __proto__
의 값은 객체나null
만 가능. 다른 자료형은 무시- 객체엔 오직 하나의
[[Portotype]]
만 존재. 객체는 두 개의 객체를 상속받지 못함
Author And Source
이 문제에 관하여(TIL_20210327), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@qkrcndtlr123/TIL20210327저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)