2015-06-17 12 views
23

Data questa classe; come potrei iterare sui metodi che include?ES6 Iterate over class methods

class Animal { 
    constructor(type){ 
     this.animalType = type; 
    } 
    getAnimalType(){ 
     console.log('this.animalType: ', this.animalType); 
    } 
} 

let cat = window.cat = new Animal('cat') 

Quello che ho cercato è il seguente senza successo:

for (var each in Object.getPrototypeOf(cat)){ 
    console.log(each); 
} 
+1

Nel caso non l'iterazione di 'Animal .prototype' lavoro? Da quello che ho capito, l'architettura dell'oggetto sottostante è sempre la stessa del "vecchio" modo. – slebetman

+0

Animal.prototype espone i metodi. Penso che il problema sia nel modo di iterare su di loro. per .. in non sembra funzionare. – seasick

risposta

39

È possibile utilizzare Object.getOwnPropertyNames sul prototipo:

Object.getOwnPropertyNames(Animal.prototype) 
// [ 'constructor', 'getAnimalType' ] 
+0

Non l'ho provato, ma funzionerà su qualcosa che ha ereditato? Non sono sicuro se lo farà ... e solo per la super classe. – seasick

+2

@seasick Funziona, ma dovrai usare 'Object.getPrototypeOf', per ottenere prima il prototipo: 'Object.getOwnPropertyNames (Object.getPrototypeOf (cat))' – Paulpro

+0

Grazie !!!! Questo sicuramente funziona, ma considerando la sintassi di tutto questo ... mi chiedo se questo è il modo preferito di fare qualcosa del genere. Quello che sto cercando è di chiamare tutti i metodi della classe, ma non voglio farlo in un modo letterale, quindi ho voluto iterare attraverso di essi. – seasick

0

controllo questo violino

https://jsfiddle.net/ponmudi/tqmya6ok/1/

class Animal { 
    constructor(type){ 
     this.animalType = type; 
    } 
    getAnimalType(){ 
     console.log('this.animalType: ', this.animalType); 
    } 
} 

let cat = new Animal('cat'); 

//by instance 
document.getElementById('1').innerHTML = Object.getOwnPropertyNames(cat); 

//by getting prototype from instance 
document.getElementById('2').innerHTML = Object.getOwnPropertyNames(Object.getPrototypeOf(cat)); 

//by prototype 
document.getElementById('3').innerHTML = Object.getOwnPropertyNames(Animal.prototype); 
0

Se è necessario ottenere anche i metodi della superclasse, è possibile chiamare ripetutamente lo Object.getPrototypeOf() finché non vengono trovati tutti. Probabilmente ti vorresti fermare quando arrivi a Object.prototype, perché i metodi in là sono fondamentali e di solito non vuoi toccarli con nessun codice che usi la riflessione.

La domanda Get functions (methods) of a class ha una risposta che include una funzione per farlo, ma ha alcuni difetti (incluso l'utilizzo di una condizione di ciclo che ha avuto un effetto collaterale di modificare un argomento di funzione, che immagino rende due scelte di stile di codice discutibili in una sola riga di codice ...), così ho riscritto qui:

export function listMethodNames (object, downToClass = Object) 
{ 
    // based on code by Muhammad Umer, https://stackoverflow.com/a/31055217/441899 
    let props = []; 

    for (let obj = object; obj !== null && obj !== downToClass.prototype; obj = Object.getPrototypeOf(obj)) 
    { 
     props = props.concat(Object.getOwnPropertyNames(obj)); 
    } 

    return props.sort().filter((e, i, arr) => e != arr[i+1] && typeof object[e] == 'function'); 
} 

oltre che fissa il bug nel codice originale (che non copiare l'oggetto in un altro variabile per il ciclo quindi, quando è stato utilizzato per il filtraggio nella riga di ritorno non era più valido) questo fornisce un argomento facoltativo per interrompere l'iterazione in una classe configurabile. Il valore predefinito sarà Object (quindi i metodi di Object sono esclusi, se si desidera includerli è possibile utilizzare una classe che non appare nella catena di ereditarietà ... forse la creazione di una classe di marcatori, ad esempio class IncludeObjectMethods{}, potrebbe avere senso). Ho anche modificato il ciclo do in un ciclo for più chiaro e ho riscritto la funzione filtro function ... vecchio stile in una funzione freccia ES6 per rendere il codice più compatto.

2

Poiché i metodi sulla classe ES6 non sono enumerabili, non è possibile utilizzare l'Object.getOwnPropertyNames() per ottenere una matrice di tutte le sue proprietà.

Dopo averlo raggiunto, ci sono diversi modi per estrarre metodi, il più semplice dei quali potrebbe utilizzare Array.prototype.forEach().

Partenza il seguente frammento:

Object.getOwnPropertyNames(Animal.prototype).forEach((value) => { 
    console.log(value); 
}) 
3

Lo so, lo so, ma hey ...

const deepProps = x => x && x !== Object.prototype && Object.getOwnPropertyNames(x).concat(deepProps(Object.getPrototypeOf(x)) || []); 
const deepFunctions = x => deepProps(x).filter(name => typeof x[ name ] === "function"); 
const userFunctions = x => new Set(deepFunctions(x).filter(name => name !== "constructor" && !~name.indexOf("__"))); 

utilizzo:

class YourObject { 
    hello() { return "uk"; } 
    goodbye() { return "eu"; } 
} 

class MyObject extends YourObject { 
    hello() { return "ie"; } 
} 

const x = new MyObject(); 
userFunctions(x); // [ "hello", "goodbye" ] 
+0

Dovrebbe essere la risposta selezionata, funziona sia per ES6 che per l'oggetto dinamico e l'ereditarietà ES6. – ktutnik