web-dev-qa-db-fra.com

Comment afficher toutes les méthodes d'un objet?

Je veux savoir comment lister toutes les méthodes disponibles pour un objet comme par exemple:

 alert(show_all_methods(Math));

Cela devrait imprimer:

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

Vous pouvez utiliser Object.getOwnPropertyNames() pour obtenir toutes les propriétés appartenant à un objet, énumérables ou non. Par exemple:

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

Vous pouvez ensuite utiliser filter() pour obtenir uniquement les méthodes:

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

Dans les navigateurs ES3 (IE 8 et versions antérieures), les propriétés des objets intégrés ne sont pas énumérables. Des objets tels que window et document ne sont pas intégrés, ils sont définis par le navigateur et probablement énumérables par conception.

De ECMA-262 Edition :

Objet global
Il existe un objet global unique (15.1), créé avant que le contrôle ne pénètre dans un contexte d'exécution. Initialement, l'objet global a les propriétés suivantes:

• Objets intégrés tels que Math, Chaîne, Date, ParseInt, etc. Ils ont des attributs {DontEnum} .
• Propriétés supplémentaires définies par l'hôte. Cela peut inclure une propriété dont la valeur est l'objet global lui-même; Par exemple, dans le modèle d'objet de document HTML, la propriété window de l'objet global est l'objet global lui-même.

Lorsque le contrôle entre dans des contextes d'exécution et que le code ECMAScript est exécuté, des propriétés supplémentaires peuvent être ajoutées à l'objet global et les propriétés initiales peuvent être modifiées.

Je signale que cela signifie que ces objets ne sont pas des propriétés énumérables de l'objet Global. Si vous parcourez le reste du document de spécification, vous verrez que l'attribut { DontEnum } est défini sur la plupart des propriétés intégrées et des méthodes de ces objets.


Mise à jour: un autre utilisateur SO, CMS, a signalé à mon attention un bug IE concernant { DontEnum } .

Au lieu de vérifier l'attribut DontEnum, JScript [Microsoft] ignorera toutes les propriétés de tout objet contenant une propriété du même nom dans la chaîne de prototypes de l'objet et possédant l'attribut DontEnum.

En bref, méfiez-vous lorsque vous nommez les propriétés de votre objet. S'il existe une propriété ou une méthode de prototype intégrée portant le même nom, alors IE l'ignorera lors de l'utilisation d'une boucle for...in.

273
Andy E

Ce n'est pas possible avec ES3 car les propriétés ont un attribut interne DontEnum qui nous empêche d'énumérer ces propriétés. ES5, en revanche, fournit des descripteurs de propriétés permettant de contrôler les capacités d’énumération des propriétés afin que les propriétés définies par l’utilisateur et les propriétés natives puissent utiliser la même interface et bénéficier des mêmes fonctionnalités, notamment la possibilité de visualiser les propriétés non énumérables par programmation.

La fonction getOwnPropertyNames peut être utilisée pour énumérer toutes les propriétés de l'objet transmis, y compris celles qui ne sont pas énumérables. Ensuite, un simple contrôle typeof peut être utilisé pour filtrer les non-fonctions. Malheureusement, Chrome est le seul navigateur sur lequel il fonctionne actuellement.

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

console.log(getAllMethods(Math));

enregistre ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"] sans ordre particulier.

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

De cette façon, vous obtiendrez toutes les méthodes que vous pouvez appeler sur obj. Cela inclut les méthodes qu'il "hérite" de son prototype (comme getMethods() en Java). Si vous voulez seulement voir ces méthodes définies directement par obj, vous pouvez vérifier avec hasOwnProperty:

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

La plupart des navigateurs modernes prennent en charge console.dir(obj), qui renverra toutes les propriétés d'un objet dont il a hérité par l'intermédiaire de son constructeur. Consultez la documentation de Mozilla pour plus d'informations et la prise en charge actuelle du navigateur.

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

La réponse courte est que vous ne pouvez pas parce que Math et Date (par coeur, je suis sûr qu'il y en a d'autres) ne sont pas des objets normaux. Pour voir cela, créez un script de test simple:

<html>
  <body>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
      $(function() {
        alert("Math: " + Math);
        alert("Math: " + Math.sqrt);
        alert("Date: " + Date);
        alert("Array: " + Array);
        alert("jQuery: " + jQuery);
        alert("Document: " + document);
        alert("Document: " + document.ready);
      });
    </script>
  </body>
</html>

Vous voyez qu'il présente comme un objet la même chose que le document dans l'ensemble, mais lorsque vous essayez réellement de voir dans cet objet, vous voyez qu'il s'agit d'un code natif et de quelque chose qui n'est pas exposé de la même manière pour l'énumération.

3
Nick Craver

Les autres réponses ici fonctionnent pour quelque chose comme Math, qui est un objet statique. Mais ils ne fonctionnent pas pour une instance d'un objet, telle qu'une date. J'ai trouvé ce qui suit au travail:

function getMethods(o) {
  return Object.getOwnPropertyNames(Object.getPrototypeOf(o))
    .filter(m => 'function' === typeof o[m])
}
//example: getMethods(new Date()):  [ 'getFullYear', 'setMonth', ... ]

https://jsfiddle.net/3xrsead0/

Ceci ne fonctionnera pas pour quelque chose comme la question initiale (Math), alors choisissez votre solution en fonction de vos besoins. Je poste ceci ici parce que Google m'a envoyé à cette question mais je voulais savoir comment faire cela pour les instances d'objets.

0
Kip

Je crois qu'il y a une simple raison historique pour laquelle vous ne pouvez pas énumérer les méthodes d'objets intégrés comme Array, par exemple. Voici pourquoi:

Les méthodes sont des propriétés de l'objet prototype, disons Object.prototype. Cela signifie que toutes les instances d'objet hériteront de ces méthodes. C'est pourquoi vous pouvez utiliser ces méthodes sur n'importe quel objet. Dites .toString () par exemple.

Donc, les méthodes IF étaient énumérables, et j'itérerais sur {a: 123} avec: "pour (entrez {a: 123}) {...}" que se passerait-il? Combien de fois cette boucle serait-elle exécutée?

Il serait itéré une fois pour la clé unique "a" dans notre exemple. MAIS ÉGALEMENT une fois pour chaque enumerable propriété de Object.prototype. Donc, si les méthodes étaient énumérables (par défaut), alors toute boucle sur un objet le serait également sur toutes ses méthodes héritées.

0
Panu Logic