TypeScript-konstruktører som returnerer et objekt erstatter implisitt verdien av `this` for alle kallere av `super(...)`?
Jeg prøver å forstå en setning i håndboken:
I ES2015, konstruktører som returnerer et objekt implisitt erstatter verdien av
thisfor alle kallere avsuper(...). Det er nødvendig for generert konstruktørkode å fange opp enhver potensiell returverdi frasuper(...)og erstatte den medthis.
Hele linjen er vag for meg. Kan noen forklare hva som skjedde her?
Svar #1
Den super "funksjonskallet" er merkelig. For vanlige klasser som ikke returnerer objekter, er this bare den nåværende instansen av klassen som blir konstruert. Kallet til super() opererer bare på den samme this, og dermed er det endelige konstruerte objektet en instans av subklassen:
class Foo {
a = 10;
constructor() { }
}
class Bar extends Foo {
z: number;
constructor() {
super();
this.z = 1;
}
}
const b = new Bar();
console.log(b); // Bar: {a: 10, z: 1}
console.log(b instanceof Bar); // true
Men hvis superklassen returnerer en verdi fra konstruktøren sin, blir på en eller annen måte this i subklassen den verdien. Det gjør at etterfølgende referanser til this kan referere til det samme objektet som superklassen returnerer. Så subklassen oppfører seg "normalt" bortsett fra at det konstruerte objektet faktisk ikke er en instans av klassen:
class Foo {
constructor() {
return { a: 10 };
}
}
class Bar extends Foo {
z: number;
constructor() {
super();
this.z = 1;
}
}
const b = new Bar();
console.log(b); // {a: 10, z: 1}
console.log(b instanceof Bar); // false
Det betyr at kall til super() må se ut som «kall overklassekonstruktøren som en funksjon, på en måte, og se om den returnerer noe». Hvis det gjør det, så tilordne resultatet av den funksjonen til this. Som om du kunne skrive
this = superCtor.call(this) || this;
Men du kan ikke gjøre det! Du kan ikke tilordne til this. Men det skjer likevel, implisitt. Hvis du ser på hva som skjer når superkonstruktører kalles når kode nedgraderes til en versjon av JS før class eksisterte, vil du se noe lignende:
function Bar() {
var _this = _super.call(this) || this;
_this.z = 1;
return _this;
}
Og du ser at den faktiske this har blitt erstattet med en ny _this-variabel overalt.
Lenke til kode på lekeplassen
