const Parent = class{
constructor(){
console.log('parent', new.target == Child);
}
};
const Child = class extends Parent{
constructor(){
super();
console.log('child', new.target == Child);
}
};
new Child;
//parent true
//child true
super()
를 통해 부모의 생성자가 호출되었을 때 부모 측의 new.target
도 Child를 가리키고 있다
ES5로 super 흉내 내보기
const Parent = function(){
console.log('parent', new.target);
};
const Child = function(){
this.constructor.call(this);
console.log('child', new.target);
};
Child.prototype = Object.create(Parent.prototype);
- Object.create를 사용하면 그나마 Parent가 상속을 위해 사용된 건지 진짜 생성을 위해 사용된 건지를 판별하는 수고는 덜 수 있습니다.
- 자식이 부모 생성자를 체인하는 경우
new.target
이 작동하지 않게 되는데,
- 기존 프로토 타입체인 구문 하에서의 생성자 체인은
this.constructor
를 call
로 호출했을 뿐이라 new.target
은 생성되지 않기 때문
Reflect
- Reflect는 중간에서 가로챌 수 있는 JavaScript 작업에 대한 메서드를 제공하는 내장 객체입니다. 메서드의 종류는 프록시 처리기와 동일합니다. Reflect는 함수 객체가 아니므로 생성자로 사용할 수 없습니다.
ES6 Reflect.constuct()
이용해서 super 흉내내보기
const Parent = function(){
//new.target을 전달 받아 생성될 거라 Child를 가리킬 수 있다
console.log('parent', new.target == Child);
};
const Child = function(){
//1. Child의 new.target을 전달하여 Parent를 생성할 수는 있지만,
//2. 이걸 this에 할당할 방법은 없다!
/*this =*/ Reflect.construct(this.constructor, [], new.target);
console.log('child', new.target == Child);
};
Child.prototype = Object.create(Parent.prototype);
new Child;
//parent true
//child true
- 엔진이
new
로 객체를 만드는 시점에 직접 new.target
을 전달해줘야 하기 때문에 ES5
는 이 문제를 해결할 수 있는 기존의 방법은 없다
ES6
는 Reflect.constuct()
로 가능하다
- 이를 이용하면
new.target을 전달
하여 인스턴스를 만들 수 있습니다. 만들 수 있긴 하지만 이마저도 그걸 this
와 연결할 방법은 없습니다 ^^; this
는 할당이 불가능
HomeObject
- class문에서 super를 사용할 수 있게 하는 것은 새로운 시스템인
[[HomeObject]]
덕분
- 이 속성은 class문에서
메소드가 정의되는 시점에 확정
되고 변경할 수 없습니다
- 상속받은 부모의 연결을 처리하는데 super키워드를 쓸 때 실제로 작동하게 되는 객체가 바로
HomeObject
정의 시점에 HomeObject가 확정
된다는 사실로부터 프로토타입처럼 남의 메소드를 자신의 메소드로 빌려오는 게 무의미
const ParentA = class{
methodP(){console.log('pa');}
};
const A = class extends ParentA{
methodA(){
super.methodP();
}
};
const ParentB = class{
methodP(){console.log('pb');}
};
const B = class extends ParentB{};
B.prototype.methodB = A.prototype.methodA;
const b = new B;
b.methodB(); //pa
- ParentA를 상속받은 A의 경우 이미
methodA가 정의되는 시점
에 HomeObject
로 ParentA가 지정되어 바인딩이 고정
- B가 A의 methodA를 빌려와 자신의 methodB로 만들었음에도 불구하고 methodB를 실제 호출해보면 본인 부모인 pb가 출력되지 않고 pa가 출력 → 생성시점에 이미 고정되버림