# 프로토타입 상속

# [[Prototype]] 숨김 프로퍼티

해당 객체의 [[Prototype]] 의 값

  • null
  • 다른 객체에 대한 참조
    • 참조되는 다른 객체는 해당 객체의 프로토타입이 된다.

image

  • 프로토타입 상속
    • 자바스크립트는 object 에서 해당 프로퍼티가 없으면 프로토타입에서 프로퍼티를 찾는다.

# __proto__ :[[Prototype]] 값 설정 방법

let animal = {
  eats: true
};
let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal;
1
2
3
4
5
6
7
8
  • __proto__[[Prototype]] 용 getter-setter 임
  • __proto__ 는 하위 호환성 때문에 사용할 수 있다.
  • Object.getPrototypeOf Object.setPrototypeOf 를 사용한다.

image

# 프로토타입 체인

let animal = {
  eats: true,
  walk() {
    alert("동물이 걷습니다.");
  }
};

let rabbit = {
  jumps: true,
  __proto__: animal
};

let longEar = {
  earLength: 10,
  __proto__: rabbit
};

// 메서드 walk는 프로토타입 체인을 통해 상속받았습니다.
longEar.walk(); // 동물이 걷습니다.
alert(longEar.jumps); // true (rabbit에서 상속받음)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

image

프로토타입 체이닝의 제약사항

  1. 순환 참조는 허용되지 않음.
    • 에러발생
  2. __proto__ 의 값은 [ 객체 || null ] 만 가능함. 다른 자료형은 무시
  3. 객체에는 오직 하나의 [[Prototype]] 만 존재함.

# this 가 나타내는 것.

this 는 . 앞에 있는 객체가 된다

// animal엔 다양한 메서드가 있습니다.
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이라는 프로퍼티가 없습니다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

image

메서드는 공유 되지만, 객체의 상태는 공유되지 않는다.

# for...in 반복문

상속 프로퍼티도 순회 대상에 포함된다.

let animal = {
  eats: true
};

let rabbit = {
  jumps: true,
  __proto__: animal
};

// Object.keys는 객체 자신의 키만 반환합니다.
alert(Object.keys(rabbit)); // jumps

// for..in은 객체 자신의 키와 상속 프로퍼티의 키 모두를 순회합니다.
for(let prop in rabbit) alert(prop); // jumps, eats

// obj.hasOwnProperty(key)를 응용하면 아래 예시에서처럼 상속 프로퍼티를 걸러낼 수 있고, 
// 상속 프로퍼티만을 대상으로 무언가를 할 수도 있습니다.
for(let prop in rabbit) {
  let isOwn = rabbit.hasOwnProperty(prop);

  if (isOwn) {
    alert(`객체 자신의 프로퍼티: ${prop}`); // 객체 자신의 프로퍼티: jumps
  } else {
    alert(`상속 프로퍼티: ${prop}`); // 상속 프로퍼티: eats
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

image

Object.prototype 에 있는 모든 메서드의 enumerable 플래그는 false 이므로 for..in 에서 출력되지 않는다.

  • 키값을 순회하는 대부분의 메서드는 상속 프로퍼티를 제외하고 동작한다.
  • Object.keys Object.values