Bo… nie poddając się metodom

Nov 23 2020

Biorąc pod uwagę następujące kwestie:

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()

Uruchamiam to ts-node index.tsi wszystko co otrzymuję to:

{ propOrMethod: 'dataA' }
{ propOrMethod: 'dataB' }

Bez odniesienia do myMethod. Chciałbym powtórzyć wszystkie metody mojej klasy, ale wygląda na to, że nie istnieją

Odpowiedzi

2 CertainPerformance Nov 24 2020 at 04:37

for..initeruje po wszystkich wyliczalnych właściwościach instancji i w górę łańcucha prototypów. Ale normalnych metod w klasie nie można wyliczyć:

class MyClass {
    myMethod() {
        return {
            test: 'true'
        };
    }
}
console.log(Object.getOwnPropertyDescriptor(MyClass.prototype, 'myMethod').enumerable);

Więc nie podlega iteracji.

Jeśli chcesz iterować również po niewliczalnych właściwościach, użyj Object.getOwnPropertyNames(co iteruje po własnych nazwach właściwości obiektu, więc musisz to zrobić rekurencyjnie, jeśli chcesz, aby wszystkie nazwy właściwości były w dowolnym miejscu w łańcuchu prototypów):

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();

Możesz również sprawić, że metoda będzie wyliczalna:

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();

Lub przypisz metodę po definicji klasy:

class MyClass {
    dataA = 0;
    dataB = 123;
    constructor() {
         for (const propOrMethod in this) {
            console.log({propOrMethod})
        }
    }
}
MyClass.prototype.myMethod = () => ({ test: 'true' });
const myInst = new MyClass();

Lub przypisz go do instancji w konstruktorze:

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();