简体   繁体   English

获取类的属性数组而不实例化它?

[英]Get array of class's properties without instantiating it?

It seems like you should be able to do this because building a form dynamically based off of a class definition (Angular) would work so much better if the logic could be written agnostically of the class.看起来您应该能够做到这一点,因为如果逻辑可以与类无关地编写,则基于类定义(Angular)动态构建表单会工作得更好。 This would be scalable, so an addition of a field to the class would not also require an update to the logic producing the form and template.这将是可扩展的,因此向类添加字段也不需要更新生成表单和模板的逻辑。

Is there any way to do this or even an NPM module that will do this?有没有办法做到这一点,甚至有一个 NPM 模块可以做到这一点?

I found that I can do ClassName.toString() but it would be a pain to parse that.我发现我可以做ClassName.toString()但解析它会很痛苦。 And I just might write a module to do it if nothing else.如果不出意外,我可能会编写一个模块来完成它。

I just feel like instantiating a dummy instance of the class for the purpose of enumerating over its properties is a poor strategy.我只是觉得为了枚举其属性而实例化该类的一个虚拟实例是一种糟糕的策略。

You could use Object.getOwnPropertyNames() .您可以使用Object.getOwnPropertyNames()

Example class:示例类:

class Foo { setBar() { throw Error('not implemented'); return false; } getBar() { throw Error('not implemented'); return false; } }

And then接着

Object.getOwnPropertyNames(Foo.prototype)

results in结果是

["constructor", "setBar", "getBar"]

While I was researching this I looked into Object.keys first, and although it didn't work, you may wish to reference the documentation for Object.keys 's polyfill .当我研究这个时,我首先研究了Object.keys ,虽然它不起作用,但您可能希望参考Object.keys的 polyfill 的文档 It has code for stripping out constructor , toString , and the like, as well as properly implementing hasOwnProperty .它具有用于剥离constructortoString等的代码,以及正确实现hasOwnProperty的代码。

Also see Bergi's answer here .另请参阅此处的 Bergi 回答

Any way?反正? Declare your class as a function, and put the properties on the prototype:将您的类声明为函数,并将属性放在原型上:

var Presidents = function() {
};

Presidents.prototype = {
  "washington" : "george",
  "adams" : "john"
}

console.log(Object.keys(Presidents.prototype))

// Output is
//  [ 'washington', 'adams' ]

getOwnPropertyDescriptors of a class prototype will only expose methods and accessor descriptors - data properties can not be determined without instantiation (also because constructor arguments can influence the amount, types and values of props).类原型的getOwnPropertyDescriptors只会公开方法和访问器描述符 - 没有实例化就无法确定数据属性(也因为构造函数参数会影响道具的数量、类型和值)。 There can be several reasons to not want to instantiate (eg because some static counter tracks instances) - therefore a workaround could be to dynamically create a copy of the class and instatiate that "shadow" along with sample constructor arguments.不想实例化可能有几个原因(例如,因为一些静态计数器跟踪实例) - 因此一种解决方法可能是动态创建类的副本并将该“影子”与示例构造函数参数一起实例化。

 /** * get properties from class definition without instantiating it * * @param cls: class * @param args: sample arguments to pass to shadow constructor * @usage `const props = getInstanceProperties(MyClass);` * @notice this will regex replace the classname (can be an issue with strings containing that substring) */ const getInstanceProperties = (cls, args = [], ignore = ['constructor', 'toString']) => { const className = cls.prototype.constructor.name; const shadowCode = cls.toString().replace(new RegExp(`${className}`, 'g'), `_${className}_`); const shadowClass = eval(`(${shadowCode})`); const o = new shadowClass(...args); const methodsAndAccessors = Object.getOwnPropertyDescriptors(cls.prototype); const dataDescriptors = Object.getOwnPropertyDescriptors(o); const descriptors = Object.assign({}, methodsAndAccessors, dataDescriptors); ignore.forEach(name => delete descriptors[name]); return descriptors; }; class Foo extends Object { static instances = 0; #myPrivateVar = 123; myValue=123; constructor(){ super(); this.myConstructorVar = ++Foo.instances; } myMethod() {} set myAccessor(x){} } console.log(Object.keys(getInstanceProperties(Foo)));

will return: [ 'myMethod', 'myAccessor', 'myValue', 'myConstructorProp' ]将返回: [ 'myMethod', 'myAccessor', 'myValue', 'myConstructorProp' ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM