Come visualizzare tutti i metodi di un object?

Voglio sapere come elencare tutti i metodi disponibili per un object come ad esempio:

alert(show_all_methods(Math)); 

Questo dovrebbe stampare:

 abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, … 

È ansible utilizzare Object.getOwnPropertyNames() per ottenere tutte le proprietà che appartengono a un object, che siano enumerabili o meno. Per esempio:

 console.log(Object.getOwnPropertyNames(Math)); //-> ["E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", ...etc ] 

È quindi ansible utilizzare filter() per ottenere solo i metodi:

 console.log(Object.getOwnPropertyNames(Math).filter(function (p) { return typeof Math[p] === 'function'; })); //-> ["random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", ...etc ] 

Nei browser ES3 (IE 8 e precedenti), le proprietà degli oggetti built-in non sono enumerabili. Oggetti come window e document non sono integrati, sono definiti dal browser e molto probabilmente enumerabili per design.

Da ECMA-262 Edizione 3 :

Oggetto globale
Esiste un object globale univoco (15.1), che viene creato prima che il controllo entri in qualsiasi contesto di esecuzione. Inizialmente l’object globale ha le seguenti proprietà:

• Oggetti built-in come Math, String, Date, parseInt, ecc. Questi hanno attributi {DontEnum} .
• Ulteriori proprietà definite dall’host. Questo può includere una proprietà il cui valore è l’object globale stesso; ad esempio, nel modello di object del documento HTML la proprietà della finestra dell’object globale è l’object globale stesso.

Quando il controllo entra nei contesti di esecuzione e mentre viene eseguito il codice ECMAScript, è ansible aggiungere ulteriori proprietà all’object globale e le proprietà iniziali potrebbero essere modificate.

Vorrei sottolineare che questo significa che quegli oggetti non sono proprietà enumerabili dell’object Globale. Se si esamina il resto del documento delle specifiche, si vedrà che la maggior parte delle proprietà e dei metodi incorporati di questi oggetti hanno l’attributo { DontEnum } impostato su di essi.


Aggiornamento: un altro utente SO, CMS, ha { DontEnum } alla mia attenzione un bug di IE riguardante { DontEnum } .

Invece di controllare l’attributo DontEnum, [Microsoft] JScript salterà su qualsiasi proprietà in qualsiasi object in cui esiste una proprietà con lo stesso nome nella catena di prototipi dell’object che ha l’attributo DontEnum.

In breve, fai attenzione quando dai il nome alle proprietà dell’object. Se esiste una proprietà prototipo integrata o un metodo con lo stesso nome, IE lo salterà quando utilizza un ciclo for...in loop.

Non è ansible con ES3 dato che le proprietà hanno un attributo DontEnum interno che ci impedisce di enumerare queste proprietà. D’altra parte, ES5 fornisce descrittori di proprietà per il controllo delle capacità di enumerazione delle proprietà in modo che le proprietà native definite dall’utente possano utilizzare la stessa interfaccia e godere delle stesse funzionalità, che includono la possibilità di vedere le proprietà non enumerabili a livello di codice.

La funzione getOwnPropertyNames può essere utilizzata per enumerare su tutte le proprietà dell’object passato, compresi quelli che non sono enumerabili. Quindi è ansible utilizzare un semplice controllo di tipo per escludere le non funzioni. Sfortunatamente, Chrome è l’unico browser al quale funziona attualmente.

 ​function getAllMethods(object) { return Object.getOwnPropertyNames(object).filter(function(property) { return typeof object[property] == 'function'; }); } console.log(getAllMethods(Math)); 

registra ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"] in nessun ordine particolare.

 var methods = []; for (var m in obj) { if (typeof obj[m] == "function") { methods.push(m); } } alert(methods.join(",")); 

In questo modo, otterrai tutti i metodi che puoi chiamare su obj . Ciò include i metodi che “eredita” dal suo prototipo (come getMethods() in java). Se vuoi vedere solo quei metodi definiti direttamente da obj puoi verificare con hasOwnProperty :

 var methods = []; for (var m in obj) { if (typeof obj[m] == "function" && obj.hasOwnProperty(m)) { methods.push(m); } } alert(methods.join(",")); 

Supporto per browser più moderno console.dir(obj) , che restituirà tutte le proprietà di un object che ha ereditato tramite il suo costruttore. Vedi la documentazione di Mozilla per maggiori informazioni e l’attuale supporto del browser.

console.dir(Math) => MathConstructor E: 2.718281828459045 LN2: 0.6931471805599453 ... tan: function tan() { [native code] } __proto__: Object

La risposta breve è che non puoi perché Math and Date (in cima alla mia testa, sono sicuro che ce ne sono altri) non sono oggetti normali. Per vedere questo, crea un semplice script di test:

       

Vedete che si presenta come un object nello stesso modo in cui il documento nel suo complesso, ma quando si tenta effettivamente di vedere in quell’object, si vede che è un codice nativo e qualcosa che non è esposto allo stesso modo per l’enumerazione.

Credo che ci sia un semplice motivo storico per cui non è ansible enumerare i metodi di oggetti built-in come Array, ad esempio. Ecco perché:

I metodi sono proprietà dell’object prototipo, ad esempio Object.prototype. Ciò significa che tutte le istanze Object erediteranno tali metodi. Ecco perché puoi usare questi metodi su qualsiasi object. Dì .toString () per esempio.

Quindi i metodi IF erano enumerabili, e vorrei ripetere it {a: 123} con: “for (key in {a: 123}) {…}” cosa accadrebbe? Quante volte sarebbe stato eseguito quel ciclo?

Sarebbe iterato una volta per la singola chiave ‘a’ nel nostro esempio. MA ANCHE una volta per ogni proprietà enumerabile di Object.prototype. Quindi, se i metodi fossero enumerabili (per impostazione predefinita), qualsiasi loop su qualsiasi object passerebbe in loop su tutti i suoi metodi ereditati.