如何迭代 ES6/2015 class 实例的属性

How to iterate over properties of an ES6/2015 class instance

鉴于这两个 类

class Foo{
  f1;

  get f2(){
    return "a";
  }
}

class Bar extends Foo {
  b1;

  get b2(){
    return "a";
  }
}

let bar = new Bar();

什么代码可以从 bar 实例中获取这个属性列表? ['f1', 'f2', 'b1', 'b2']

Here is a Babel sample


更新

这应该是@Marc C 的回答的一部分:

使用装饰器我可以轻松地将不可枚举的 属性 变成可枚举的 属性:

class Bar extends Foo {

  @enumerable()  
  get b2(){
    return "a";
  }

}

装饰器源代码如下:

function enumerable() {
  return function(target, key, descriptor) {
    if (descriptor) {
      descriptor.enumerable = true;
    }
  };
}

Here is a Babel sample

这不是 class 中的 valid syntax for declaring properties。相反,在构造函数中声明它们。

class Foo {
  constructor() {
    this.f1 = undefined;
  }
}

然后您可以使用 Object.keys.

获取它们

使用 Babel 中的实验性功能将允许您使用该语法声明属性,但必须声明它们的值。

class Foo {
  f1 = 0;
  ...
}

至于访问 getter,默认情况下 getter 是 non-enumerable,不能使用 Object.keys 或任何类似机制访问。但是,您可以使用 Object.defineProperty.

创建可枚举的 getter
Object.defineProperty(bar, 'f2', {
  get() { 
    return "a"; 
  }
});

如果您使用的是实验性 ES7 功能,则可以应用 decorator to the class method and get the same behavior. See this Babel sample

class Foo {
  @enumerable()
  get b2() {
    return "a";
  }
}

function enumerable() {
  return function(target, key, descriptor) {
    if (descriptor) {
      descriptor.enumerable = true;
    }
  }
}

我觉得之前有人回答过这个问题。您可以将 Object.getOwnPropertyNames 应用于实例及其原型:

function getAllPropertyNames(obj) {
  let names = [];
  do {
    names.push.apply(names, Object.getOwnPropertyNames(obj));
    obj = Object.getPrototypeOf(obj);
  } while(obj !== Object.prototype);
  return names.filter(name => name !== 'constructor');
}