在扩展基础 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。
我有这样的代码
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。