Find all classes in a Javascript application that

2019-06-21 03:46发布

I have code like this

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

I want to look at all of the classes in my application's universe, and when I find 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 having to update a 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 extra functionality to my classes or call them explicitly.

3条回答
看我几分像从前
2楼-- · 2019-06-21 04:16

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.

查看更多
看我几分像从前
3楼-- · 2019-06-21 04:37

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..

查看更多
劫难
4楼-- · 2019-06-21 04:38

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?

查看更多
登录 后发表回答