Obtener funciones (métodos) de una clase [duplicado]
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
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.
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;
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]);