在扩展基础 class 的 Javascript 应用程序中查找所有 classes

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

我有这样的代码

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

我想查看我的应用程序宇宙中的所有 类,当我找到一个从 Animal 派生的对象时,我想创建一个该类型的新对象并将其添加到列表中。这允许我添加功能而无需更新事物列表。所以我可以避免以下情况:

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

PS:我不想向我的 类 添加额外的功能或显式调用它们。

这是我目前的发现 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

和魔法

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;
}

这种方法的主要缺点是我不能使用 ES6 模块导入,只能做老式的简单文件连接,但这总比什么都不做要好。

PS: 还在等待更好的答案

UPD:是的,我知道要使用这一切 类 必须全局定义,这就是为什么我寻找更好的方法来做到这一点..

这是不可能的。你永远不会知道例如关于局部 类 在某个函数内定义,或在另一个模块中私下定义。这是设计使然。这将是非模块化的并且会破坏封装。

此外,类 的集合在 JavaScript 中不是静态的。您可以无限地动态创建新的 类。

如果您认为自己需要这样的功能,那么我强烈建议您错了。你想达到什么目的?

我认为您可以使用装饰器。例如,您可以创建一个 @Extends() 并提供基数 class 作为参数,例如@Extends(Animal)。在装饰器函数中,您可以使用 @Extends 装饰的 class 的名称并将其放入数组或对象中。不知道它是否适用于浏览器,但应该适用。在带有 TypeScript 的节点中,我会做类似的事情:

import { MyClassMetadata } from './';

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

然后您可以访问存储给定 class 的子数组的 MyClassMetadata 变量,并按您想要的方式使用它。你可以玩玩它并获得想要的结果。

这个怎么样:

class Animal {
  static derived = new Set();
}
class Dog extends Animal {
  static dummy = Animal.derived.add(this.name);
}
class Cat extends Animal {
  static dummy = Animal.derived.add(this.name);
}
class Donkey extends Animal {
  static dummy = Animal.derived.add(this.name);
}

console.log(Animal.derived);

我在 TypeScript 环境中试过这个。结果:

Set(3) {"Dog", "Cat", "Donkey"}

没有实例化 class。