【问题标题】:Iterate through methods and properties of an ES6 class遍历 ES6 类的方法和属性
【发布时间】:2016-06-12 06:36:34
【问题描述】:

因此,随着使用 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 拥有的方法以及可选的属性?

【问题讨论】:

    标签: javascript loops ecmascript-6


    【解决方案1】:

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

    因此,您可以通过以下方式获取名称数组(无需构造类的实例):

    Object.getOwnPropertyNames(MyClass.prototype)
    

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

    Object.keys(myInstance)
    

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

    【讨论】:

    • 您好,您的第二个建议对我不起作用。这是一个codePen示例codepen.io/seb-rom-o/pen/xxVxxGN?editors=0012我做错了吗?
    • @538ROMEO 是的 - 你的 class A 没有属性。请再次阅读上面的文字 - 您需要使用第一个来获取方法和第二个来获取属性。
    【解决方案2】:

    有一种方法可以仅查找方法的名称。以下已在 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)]
    

    【讨论】:

      【解决方案3】:

      是的有可能

      我使用了一个 util 函数,它可以:

      • 获取未实例化类的方法名称
      • 属于实例化类
      • 递归获取父类的所有方法

      像这样使用它:

      class A {
          fn1() { }
      }
      
      class B extends A {
          fn2() { }
      }
      
      const instanciatedB = new B();
      
      console.log(getClassMethodNames(B)) // [ 'fn2' ]
      console.log(getClassMethodNames(instanciatedB)) // [ 'fn2', 'fn1' ]
      

      这里是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(B.prototype);
          return allMethods.filter(name => name !== 'constructor' && !name.startsWith('__'))
      }
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 是的,我已经尝试过您的第二种方法,但不起作用。第一个在实例化var myclass = new MyClass() 类的新实例之前根本不起作用。即使在那之后,它也只返回属性,而不是类上的方法——这就是我正在寻找的......
        • 也许我们可以在类中做一个循环并将它作为一个对象返回?你也试过吗?
        猜你喜欢
        • 2021-12-28
        • 2012-10-29
        • 2011-12-30
        • 2010-10-26
        • 1970-01-01
        • 2015-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多