reflektion - TypeScript - getOwnPropertyNames() - Konstruktörsegenskaper vs. Getter/Setter
Jag är ganska ny på TypeScript och det finns en punkt jag inte riktigt förstår.
Föreställ dig följande klasser:
export class PropertyInConstructor {
constructor(public foo: boolean) {
}
}
export class PropertyWithGetSet {
private _foo: boolean = false;
get foo(): boolean {
return this._foo;
}
set foo(theFoo: boolean) {
this._foo = theFoo;
}
}
Enligt min förståelse ger dessa två tillvägagångssätt mig båda en egenskap som jag kan komma åt med new PropertyInConstructor().foo eller new PropertyWithGetSet().foo.
Jag vill nu få de befintliga egenskaperna hos en sådan klass (utan instans!) och prova det:
console.log(Object.getOwnPropertyNames(PropertyInConstructor.prototype));
console.log(Object.getOwnPropertyNames(PropertyWithGetSet.prototype));
["konstruktör"]
["konstruktör", "foo"]
Varför är det så att anropet där egenskaperna specificeras inne i konstruktören inte lägger till egenskapen "foo"?
Finns det något som saknas eller något annat sätt att få de egenskaperna?
Svar #1
Kort svar: de flesta egenskaper läggs till på instansen dynamiskt vid körning. Egenskaper med getters och setters måste läggas till i prototypen med Object.defineProperty.
Lagt till vid körning
Med ditt första exempel:
export class PropertyInConstructor {
constructor(public foo: boolean) {
}
}
Egenskapen läggs endast till på instansen när konstruktorn körs. Här är den transpilerade JavaScript-koden:
var PropertyInConstructor = /** @class */ (function () {
function PropertyInConstructor(foo) {
this.foo = foo;
}
return PropertyInConstructor;
}());
I praktiken existerar inte egenskapen foo på klassen förrän konstruktorn körs.
Detta är inte bara för konstruktörsegenskaper, det är för alla egenskaper som inte är definierade på prototypen, till exempel:
class PropertyInConstructor {
public foo: boolean;
constructor() {
this.foo = true;
}
}
Definiera egendom
När du använder get och set är saker annorlunda, eftersom egenskapen läggs till prototypen:
var PropertyWithGetSet = /** @class */ (function () {
function PropertyWithGetSet() {
this._foo = false;
}
Object.defineProperty(PropertyWithGetSet.prototype, "foo", {
get: function () {
return this._foo;
},
set: function (theFoo) {
this._foo = theFoo;
},
enumerable: true,
configurable: true
});
return PropertyWithGetSet;
}());
