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

I have code like this

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

      

I want to see all the classes in the universe of my application, and when I find the one that descends from Animal, I want to create a new object of that type and add it to the list. This allows me to add functionality without updating the list of things. So I can avoid the following:

var animals = [];
animals.push( new Dog() );
animals.push( new Cat() );
animals.push( new Donkey() );

      

PS: I don't want to add additional functionality to my classes or call them explicitly.

+3


source to share


3 answers


Here is what I have 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 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 cannot use ES6 module imports and have to do old fashioned and simple file concatenation, but it's still better than nothing.

PS: still expect a better answer

UPD: and you, I know that in order to use this, all classes must be defined globally, so I am looking for a better way to do this.

+1


source


It's impossible. You will never know, for example. about local classes defined inside some function, or privately in another module. And that's by design. This will be non-modular and break encapsulation.

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



If you think you want this kind of functionality, I highly recommend you do it wrong. What are you trying to achieve?

+2


source


I think you could use decorators. For example, you can create @Extends()

one and provide a base class as an argument, eg. @Extends(Animal)

... Inside the decorator function, you can take the name of the class decorated with @Extends and put it in an array or object. I 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 the array of children of the given class and use it however you want. You can play with it and get the desired result.

+1


source







All Articles