obe*_*iro 7 javascript oop ecmascript-harmony ecmascript-6
我有这样的代码
class Animal{}
class Dog extends Animal {}
class Cat extends Animal {}
class Donkey extends Animal {}
Run Code Online (Sandbox Code Playgroud)
我想查看我的应用程序的Universe中的所有类,当我找到一个来自Animal的类时,我想创建一个该类型的新对象并将其添加到列表中.这允许我添加功能而无需更新事物列表.所以我可以避免以下情况:
var animals = [];
animals.push( new Dog() );
animals.push( new Cat() );
animals.push( new Donkey() );
Run Code Online (Sandbox Code Playgroud)
PS:我不想为我的类添加额外的功能或明确地调用它们.
那这个呢:
\nclass Animal {\n static derived = new Set();\n}\nclass Dog extends Animal {\n static dummy = Animal.derived.add(this.name);\n}\nclass Cat extends Animal {\n static dummy = Animal.derived.add(this.name);\n}\nclass Donkey extends Animal {\n static dummy = Animal.derived.add(this.name);\n}\n\nconsole.log(Animal.derived);\nRun Code Online (Sandbox Code Playgroud)\n我在 TypeScript 环境中尝试过这个。结果:
\nSet(3)\xc2\xa0{"Dog", "Cat", "Donkey"}\nRun Code Online (Sandbox Code Playgroud)\n无需实例化类。
\n这是我到目前为止发现的 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
Run Code Online (Sandbox Code Playgroud)
和魔法
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;
}
Run Code Online (Sandbox Code Playgroud)
这种方法的主要缺点是我无法使用 ES6 模块导入,并且必须执行老式且简单的文件连接,但这仍然比什么都不做要好。
PS:仍在等待更好的答案
UPD:是的,我知道要使用它,所有类都必须在全局范围内定义,这就是为什么我寻找更好的方法来做到这一点。
我认为你可以使用装饰器。例如,您可以创建@Extends()一个并提供基类作为参数,例如@Extends(Animal). 在装饰器函数中,您可以获取用@Extends 装饰的类的名称,并将其放入数组或对象中。不知道它是否适用于浏览器,但应该适用。在带有 TypeScript 的 Node 中,我会执行以下操作:
import { MyClassMetadata } from './';
export function Extends(parent): (...args: any[]) => void {
return (target: object): void => {
MyClassMetadata.someVariableToStoreChildren[parent.constructor.name].push(
target,
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以访问存储给定类的子项数组的 MyClassMetadata 变量,并以您想要的方式使用它。您可以使用它并获得所需的结果。