迭代ES6类的方法和属性

时间:2016-06-12 06:36:34

标签: javascript loops ecmascript-6

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

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

e.g。 (带对象)

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方法,以及可选的属性?

4 个答案:

答案 0 :(得分:14)

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

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

Object.getOwnPropertyNames(MyClass.prototype)

如果不创建实例,则无法获取属性,但这样做可以使用Object.keys函数,该函数仅返回对象的可枚举属性:

Object.keys(myInstance)

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

答案 1 :(得分:1)

有一种方法只能找到方法的名称。以下内容已在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)]

答案 2 :(得分:0)

有可能

这是我用作获取结果的函数:

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' ]

答案 3 :(得分:-1)

我没有测试过,但我认为有两种方法可以做到。 第一个是返回'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);
}