Obtener funciones (métodos) de una clase [duplicado]

Resuelto Jan asked hace 9 años • 5 respuestas

Tengo que buscar dinámicamente las propiedades y funciones de una clase ES6. ¿Es esto siquiera posible?

Usando un bucle for...in, solo puedo recorrer las propiedades de una instancia de clase:

class Foo {
  constructor() {
    this.bar = "hi";
  }
  someFunc() {
    console.log(this.bar);
  }
}
var foo = new Foo();
for (var idx in foo) {
  console.log(idx);
}

Producción:

bar
Jan avatar Jun 25 '15 22:06 Jan
Aceptado

Los miembros de una clase no son enumerables . Para obtenerlos, debes usar Object.getOwnPropertyNames:

var propertyNames = Object.getOwnPropertyNames(Object.getPrototypeOf(foo));
// or
var propertyNames = Object.getOwnPropertyNames(Foo.prototype);

Por supuesto, esto no obtendrá métodos heredados. No existe ningún método que pueda proporcionarlos todos. Tendrías que recorrer la cadena de prototipos y obtener las propiedades de cada prototipo individualmente.

Felix Kling avatar Jun 25 '2015 15:06 Felix Kling

Esta función obtendrá todas las funciones. Heredado o no, enumerable o no. Todas las funciones están incluidas.

function getAllFuncs(toCheck) {
    const props = [];
    let obj = toCheck;
    do {
        props.push(...Object.getOwnPropertyNames(obj));
    } while (obj = Object.getPrototypeOf(obj));
    
    return props.sort().filter((e, i, arr) => { 
       if (e!=arr[i+1] && typeof toCheck[e] == 'function') return true;
    });
}

hacer prueba

getAllFuncs([1,3]);

salida de consola:

["constructor", "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight", "entries", "keys", "constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "__defineGetter__", "__lookupGetter__", "__defineSetter__", "__lookupSetter__"]

Nota

No devuelve funciones definidas mediante símbolos;

Muhammad Umer avatar Jun 25 '2015 15:06 Muhammad Umer

ES6 agrega Reflection, lo que hace que el código para hacer esto sea un poco más limpio.

function getAllMethodNames(obj) {
  let methods = new Set();
  while (obj = Reflect.getPrototypeOf(obj)) {
    let keys = Reflect.ownKeys(obj)
    keys.forEach((k) => methods.add(k));
  }
  return methods;
}


/// a simple class hierarchy to test getAllMethodNames


// kind of like an abstract base class
class Shape {
  constructor() {}
  area() {
    throw new Error("can't define area for generic shape, use a subclass")
  }
}

// Square: a shape with a sideLength property, an area function and getSideLength function
class Square extends Shape {
  constructor(sideLength) {
    super();
    this.sideLength = sideLength;
  }
  area() {
    return this.sideLength * this.sideLength
  };
  getSideLength() {
    return this.sideLength
  };
}

// ColoredSquare: a square with a color
class ColoredSquare extends Square {
  constructor(sideLength, color) {
    super(sideLength);
    this.color = color;
  }
  getColor() {
    return this.color
  }
}


let temp = new ColoredSquare(2, "red");
let methods = getAllMethodNames(temp);
console.log([...methods]);
Expandir fragmento

skav avatar Nov 13 '2016 18:11 skav