繁体   English   中英

遍历 ES6 类的方法和属性

[英]Iterate through methods and properties of an ES6 class

因此,随着使用 JavaScript 的新框架的增长,许多人采用了 ECMAScript 6 shim 或 TypeScript,具有许多新功能。 我的问题是这样的:

如何迭代 ES6 类的方法/属性?

例如(与对象)

var obj = {
  prop: 'this is a property',
  something: 256,
  method: function() { console.log('you have invoked a method'); }
}

for (var key in obj) {
  console.log(key);
}

// => 'prop'
// => 'something'
// => 'method'

(有课)

class MyClass {
  constructor() {
    this.prop = 'prop';
    this.something = 256;
  }

  method() {
    console.log('you have invoked a method');
  }
}

如何列出MyClass具有的方法,以及可选的属性?

constructor和任何定义的方法是类prototype对象的不可枚举属性。

因此,您可以使用以下命令获取名称数组(无需构造类的实例):

Object.getOwnPropertyNames(MyClass.prototype)

您不能在不创建实例的情况下获取属性,但这样做后您可以使用Object.keys函数,该函数仅返回对象的可枚举属性:

Object.keys(myInstance)

AFAIK 没有标准方法可以同时从原型中获取不可枚举属性和实例的可枚举属性。

有一种方法可以仅查找方法的名称。 以下已在 nodeJS v10.9.0 中测试,没有特殊标志。

首先,我们将一个新方法注入到 Object 中。

Object.methods = function(klass) {
  const properties = Object.getOwnPropertyNames(klass.prototype)
  properties.push(...Object.getOwnPropertySymbols(klass.prototype))
  return properties.filter(name => {
    const descriptor = Object.getOwnPropertyDescriptor(klass.prototype, name)
    if (!descriptor) return false
    return 'function' == typeof descriptor.value && name != 'constructor'
  })
}

您可以在上面看到,有必要专门排除构造函数,因为它不是严格意义上的类的方法。

创建一些包含构造函数、访问器和方法的类

class Test {
  constructor(x, y) {
    this.x = x
    this.y = y
  }
  sum() { return x + y }
  distanceFromOrigin() { return Math.sqrt(this.squareX + this.squareY) }
  get squareX() { return this.x * this.x }
  get squareY() { return this.y * this.y }
  [Symbol.iterator]() {
    return null // TODO
  }
}

让我们看看这是如何工作的

> console.log(Object.methods(Test))

Array(3) ["sum", "distanceFromOrigin", Symbol(Symbol.iterator)]

是的,这是可能的

这是我用作实用程序来获得该结果的函数:

function getClassMethodNames(klass) {
    const isGetter = (x, name) => (Object.getOwnPropertyDescriptor(x, name) || {}).get;
    const isFunction = (x, name) => typeof x[name] === 'function';
    const deepFunctions = x =>
        x !== Object.prototype &&
        Object.getOwnPropertyNames(x)
            .filter(name => isGetter(x, name) || isFunction(x, name))
            .concat(deepFunctions(Object.getPrototypeOf(x)) || []);
    const distinctDeepFunctions = klass => Array.from(new Set(deepFunctions(klass)));

    const allMethods = typeof klass.prototype === "undefined" ? distinctDeepFunctions(klass) : Object.getOwnPropertyNames(B.prototype);
    return allMethods.filter(name => name !== 'constructor' && !name.startsWith('__'))
}

像这样使用它:

class A {
    fn1() { }
}

class B extends A {
    fn2() { }
}

const instanciatedB = new B();

console.log(getClassMethodNames(B)) // [ 'fn2' ]
console.log(getClassMethodNames(instanciatedB)) // [ 'fn2', 'fn1' ]

我还没有测试过,但我仍然认为有两种方法可以做到。 第一个是返回“this”环境并对其进行循环。 第二个与 Javascript 的对象相同。 第一个示例:-(未经测试)

class MyClass {
  constructor() {
    this.prop = 'prop';
    this.something = 256;
  }

  method() {
    console.log('you have invoked a method');
  }
  get getthis()
  {
    return this;
  }
}

for( var key in MyClass.getthis )
{
    console.log(key);
}

这是第二种方法:-(未经测试)

class MyClass {
  constructor() {
    this.prop = 'prop';
    this.something = 256;
  }

  method() {
    console.log('you have invoked a method');
  }

}

for( var key in MyClass )
{
    console.log(key);
}

暂无
暂无

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

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