Por ... en no ceder métodos
Dado lo siguiente:
export class MyClass {
public dataA = 0
private dataB = 123
public myMethod(): any {
return {
test: 'true'
}
}
constructor() {
for (const propOrMethod in this) {
console.log({propOrMethod})
}
}
}
const myInst = new MyClass()
Ejecuto esto con ts-node index.tsy todo lo que obtengo es:
{ propOrMethod: 'dataA' }
{ propOrMethod: 'dataB' }
Sin referencia a myMethod. Me gustaría iterar sobre todos los métodos de mi clase, pero no parecen existir.
Respuestas
for..initera sobre todas las propiedades enumerables de la instancia y asciende por la cadena del prototipo. Pero los métodos normales en una clase no son enumerables:
class MyClass {
myMethod() {
return {
test: 'true'
};
}
}
console.log(Object.getOwnPropertyDescriptor(MyClass.prototype, 'myMethod').enumerable);
Por lo que no se repite.
Si también desea iterar sobre propiedades no enumerables, use Object.getOwnPropertyNames(que itera sobre los propios nombres de propiedad del objeto , por lo que deberá hacerlo de forma recursiva si desea que todos los nombres de propiedad en cualquier lugar de la cadena del prototipo):
const recurseLog = obj => {
for (const name of Object.getOwnPropertyNames(obj)) {
console.log(name);
}
const proto = Object.getPrototypeOf(obj);
if (proto !== Object.prototype) recurseLog(proto);
};
class MyClass {
dataA = 0;
dataB = 123;
constructor() {
recurseLog(this);
}
myMethod() {
return {
test: 'true'
};
}
}
const myInst = new MyClass();
También puede hacer que el método sea enumerable:
class MyClass {
dataA = 0;
dataB = 123;
constructor() {
for (const propOrMethod in this) {
console.log({propOrMethod})
}
}
myMethod() {
return {
test: 'true'
};
}
}
Object.defineProperty(MyClass.prototype, 'myMethod', { enumerable: true, value: MyClass.prototype.myMethod });
const myInst = new MyClass();
O asigne el método después de la definición de clase:
class MyClass {
dataA = 0;
dataB = 123;
constructor() {
for (const propOrMethod in this) {
console.log({propOrMethod})
}
}
}
MyClass.prototype.myMethod = () => ({ test: 'true' });
const myInst = new MyClass();
O asígnelo a la instancia en el constructor:
class MyClass {
dataA = 0;
dataB = 123;
constructor() {
this.myMethod = this.myMethod;
for (const propOrMethod in this) {
console.log({propOrMethod})
}
}
myMethod() {
return {
test: 'true'
};
}
}
const myInst = new MyClass();