Find all classes in a Javascript application that extend a base class

后端 未结 3 2017
陌清茗
陌清茗 2020-12-17 18:08

I have code like this

class Animal{}
class Dog extends Animal {}
class Cat extends Animal {}
class Donkey extends Animal {}

I want to look

相关标签:
3条回答
  • Here what I discovered so far http://jsbin.com/xiroyurinu/1/edit?js,console,output

    class Animal{}
    class Dog extends Animal {}
    class Cat extends Animal {}
    class Donkey extends Animal {}
    
    var animals = getAllSubclasses(Animal);
    
    console.log(animals.map(function(c){ return new window[c] })) // creates objects
    document.body.innerText = animals; // Dog, Cat, Donkey
    

    and the magic

    function getAllSubclasses(baseClass) {
      var globalObject = Function('return this')(); 
      var allVars = Object.keys(globalObject);
      var classes = allVars.filter(function (key) {
      try {
        var obj = globalObject[key];
            return obj.prototype instanceof baseClass;
        } catch (e) {
            return false;
        }
      });
      return classes;
    }
    

    The main disadvantage of this method is that I can not use ES6 module import and have to do old fashioned and simple contatenation of files, but this is still better that nothing.

    PS: still wait for better answer

    UPD: and ye, i know that to use this all classes must be defined globally, that's why i search for better way to do this..

    0 讨论(0)
  • 2020-12-17 18:57

    It is not possible. You can never know e.g. about local classes defined inside some function, or privately in another module. And that's by design. It would be unmodular and break encapsulation.

    Also, the set of classes is not static in JavaScript. You can create new classes dynamically open-endedly.

    If you think you want such functionality then I strongly suggest you're holding it wrong. What are you trying to achieve?

    0 讨论(0)
  • 2020-12-17 19:13

    I think you could make use of decorators. For instance, you could create @Extends() one and provide base class as an argument, e.g. @Extends(Animal). Inside the decorator function, you could take the name of the class decorated with @Extends and and put it into an array or an object. Don't know if it is applicable in browsers, but it should be. In Node with TypeScript I would do something like:

    import { MyClassMetadata } from './';
    
    export function Extends(parent): (...args: any[]) => void {
        return (target: object): void => {
            MyClassMetadata.someVariableToStoreChildren[parent.constructor.name].push(
                target,
            );
        }
    }
    

    Then you can access the MyClassMetadata variable that stores array of children of a given class and use it the way you want. You can play with it and get the desired result.

    0 讨论(0)
提交回复
热议问题