Iterate through methods and properties of an ES6 class

The constructor and any defined methods are non-enumerable properties of the class's prototype object.

You can therefore get an array of the names (without constructing an instance of the class) with:

Object.getOwnPropertyNames(MyClass.prototype)

You cannot obtain the properties without creating an instance, but having done so you can use the Object.keys function which returns only the enumerable properties of an object:

Object.keys(myInstance)

AFAIK there's no standard way to obtain both the non-enumerable properties from the prototype and the enumerable properties of the instance together.


Yes it is possible

I use an util function that can:

  • get method names of a not instanciated class
  • of instanciated class
  • that recursively gets all method of parent classes

Use it like:

class A {
    fn1() { }
}

class B extends A {
    fn2() { }
}

const instanciatedB = new B();

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

Here is the util function code:

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('__'))
}

There is a way to find the names of the methods only. The following has been tested in nodeJS v10.9.0 with no special flags.

First we inject a new method into 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'
  })
}

You can see above that it is necessary to specifically exclude the constructor as it is not strictly a method of the class.

Create some class containing a constructor, accessors and methods

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
  }
}

Let's see how this works

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

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