super [[HomeObject]]

lee jae hwan·2022년 7월 30일

javascript

목록 보기
67/107
class Rabbit extends Animal {
  constructor(){
     super();
  }
}

super의 주체는 무엇인가?
나의 super의미가 내포되어있어 하위클래스 생성객체가 된다.


let animal = {
  name: "동물",
  eat() {
    console.log(`${this.name} 이/가 먹이를 먹습니다.`);
  }
};

let rabbit = {
  __proto__: animal,
  name: "토끼",
  eat() {
  	this.__proto__.eat.call(this);
    super.eat();
  }
};
rabbit.eat(); 

rabbit에서 상위객체의 this가있는 메소드를 호출하려면 this를 바인딩해야 한다.
this.__proto__.eat.call(this);
상위객체로 접근하면 위와같이 반드시 this를 원하는 객체로 바인딩해야 한다.

super.eat();
자신객체로부터 상위객체메소드를 연결한후 호출하는 방식으로 this를 바인딩하지 않아도 된다.



모든 객체메서드는 [[HomeObject]]숨김속성을 가지며 해당 객체가 참조할당된다.

super는 [[HomeObject]]를 이용해 상위객체를 참조한다.

let animal = {
  name: "동물",
  eat() {
    alert(`${this.name} 이/가 먹이를 먹습니다.`);
  }
};

let rabbit = {
  __proto__: animal,
  eat() {
    // call을 사용해 컨텍스트를 옮겨가며 부모(animal) 메서드를 호출합니다.
    this.__proto__.eat.call(this); // (*)
  }
};

let longEar = {
  __proto__: rabbit,
  eat() {
    // longEar를 가지고 무언가를 하면서 부모(rabbit) 메서드를 호출합니다.
    this.__proto__.eat.call(this); // (**)
  }
};

longEar.eat();

위와같이 this.__proto을 사용해서 상위객체 메소드를 찾아가면 무한루프에빠진다. 원인은 this바인딩될때 this.proto__의 this도 바인딩되기 때문이다.

let animal = {
  name: "동물",
  eat() {         // animal.eat.[[HomeObject]] == animal
    alert(`${this.name} 이/가 먹이를 먹습니다.`);
  }
};

let rabbit = {
  __proto__: animal,
  name: "토끼",
  eat() {         // rabbit.eat.[[HomeObject]] == rabbit
    super.eat();
  }
};

let longEar = {
  __proto__: rabbit,
  name: "귀가 긴 토끼",
  eat() {         // longEar.eat.[[HomeObject]] == longEar
    super.eat();
  }
};

// 이제 제대로 동작합니다
longEar.eat(); 

super를 사용하면 정확한 상위객체를 찾는다.




[[HomeObject]]의 부작용
[[HomeObject]]는 객체메소드의 숨김속성으로 자신객체를 참조할당한다고 했다.
한번 설정된 [[HomeObject]]는 변경이 불가하며 [[HomeObject]]속성은 super에의해서만 사용된다.

객체메소드가 다른 객체의 메소드로 할당되고 super가 호출되면 [[HomeObject]]에 이전 객체정보가 저장되어있어 super는 제대로 평가되지 않는다.




let animal = {
  eat() {
    console.log(1);
  }
};

let rabbit = {
  __proto__: animal,
  eat: function() {
    super.eat();
  }
};

rabbit.eat(); 

객체메소드를 정의할때 표현식기법으로 정의하면 함수가 호출될때 메소드가 생성되기때문에 [[HomeObject]]속성이 설정되지 않는다.

반드시

let rabbit = {
  __proto__: animal,
  eat() {
    super.eat();
  }
};

함수정의방식으로 정의해야 한다.

0개의 댓글