迭代ES6类的方法和属性

Aᴄʜ*_*ᴀɪʟ 5 javascript loops ecmascript-6

因此随着使用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'
Run Code Online (Sandbox Code Playgroud)

(带课程)

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

  method() {
    console.log('you have invoked a method');
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Aln*_*tak 16

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

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

Object.getOwnPropertyNames(MyClass.prototype)
Run Code Online (Sandbox Code Playgroud)

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

Object.keys(myInstance)
Run Code Online (Sandbox Code Playgroud)

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


538*_*MEO 5

更进一步,这里有一个可以获取方法名称的函数:

  • 未实例化的类
  • 实例化类
  • 递归地遍历所有父类

这是不可能的Object.getOwnPropertyNamesObject.keys

像这样使用它:

class A {
    fn1() { }
}

class B extends A {
    fn2() { }
}

const instanciatedB = new B();

console.log(getClassMethodNames(B)) // [ 'fn2' ]
console.log(getClassMethodNames(instanciatedB)) // [ 'fn2', 'fn1' ]
Run Code Online (Sandbox Code Playgroud)

这是util函数代码:

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(klass.prototype);
    return allMethods.filter(name => name !== 'constructor' && !name.startsWith('__'))
}
Run Code Online (Sandbox Code Playgroud)