Jak wyświetlić wszystkie metody obiektu?

Chcę wiedzieć jak wyświetlić listę wszystkich metod dostępnych dla obiektu, takich jak na przykład:

 alert(show_all_methods(Math));

To powinno wydrukować:

abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
Author: Sebastian Simon, 2010-02-13

8 answers

Możesz użyć Object.getOwnPropertyNames() aby uzyskać wszystkie właściwości należące do obiektu, niezależnie od tego, czy można je wyliczyć, czy nie. Na przykład:

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

Możesz wtedy użyć filter() aby uzyskać tylko metody:

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

W przeglądarkach ES3 (IE 8 i niższych) właściwości wbudowanych obiektów nie są wyliczane. Obiekty takie jak window i document nie są wbudowane, są definiowane przez przeglądarkę i najprawdopodobniej wyliczane przez projekt.

Z ECMA-262 Edition 3:

Global Object
Istnieje unikalny globalny obiekt (15.1), który jest tworzony przed Kontrola wchodzi w dowolny kontekst wykonania. Początkowo globalny obiekt ma następujące właściwości:

• wbudowany obiekty takie jak Math, String, Date, parseInt itp. mają one atrybuty { DontEnum } .
* Dodatkowy host zdefiniowany właściwości. Może to obejmować właściwość, której wartość jest globalna samego obiektu; dla przykład, w HTML document object model okna właściwością obiektu globalnego jest sam obiekt globalny.

Jako kontrola wprowadza konteksty wykonania, a jako Wykonywany jest kod ECMAScript, dodatkowe właściwości mogą być dodawane do obiekt globalny i początkowy właściwości mogą ulec zmianie.

Powinienem zauważyć, że oznacza to, że te obiekty nie są wyliczalnymi właściwościami obiektu globalnego. Jeśli przejrzysz resztę specyfikacji dokument, zobaczysz, że większość wbudowanych właściwości i metod tych obiektów ma ustawiony atrybut { DontEnum }.


Update: kolega so user, CMS, przyniósł błąd IE dotyczący { DontEnum } do mojej uwagi.

Zamiast sprawdzania atrybutu DontEnum, [Microsoft] JScript pominie dowolną właściwość w dowolnym obiekcie, w którym w łańcuchu prototypów obiektu znajduje się właściwość o tej samej nazwie, która ma atrybut DontEnum.

W skrócie, uważaj, nazywając swoje właściwości obiektu. Jeśli istnieje wbudowana właściwość prototypu lub Metoda o tej samej nazwie, to IE pominie ją przy użyciu pętli for...in.

 321
Author: Andy E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 10:20:04

Nie jest to możliwe w przypadku ES3, ponieważ właściwości mają wewnętrzny atrybut DontEnum, który uniemożliwia nam wyliczenie tych właściwości. Z drugiej strony ES5 dostarcza deskryptory właściwości do kontrolowania możliwości wyliczania właściwości, dzięki czemu zdefiniowane przez użytkownika i natywne właściwości mogą korzystać z tego samego interfejsu i korzystać z tych samych możliwości, co obejmuje możliwość programowego wyświetlania niemożliwych do wyliczenia właściwości.

Funkcja getOwnPropertyNames może być użyta do wyliczenia wszystkich właściwości obiektu przekazanego, w tym te, które nie są wyliczalne. Następnie można zastosować proste sprawdzenie typeof, aby odfiltrować Nie-funkcje. Niestety Chrome jest obecnie jedyną przeglądarką, na której działa.

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

console.log(getAllMethods(Math));

Dzienniki ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"] w żadnej konkretnej kolejności.

 71
Author: Anurag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-01 00:25:24
var methods = [];
for (var m in obj) {
    if (typeof obj[m] == "function") {
        methods.push(m);
    }
}
alert(methods.join(","));

W ten sposób otrzymasz wszystkie metody, które możesz wywołać obj. Obejmuje to metody, które "dziedziczy" ze swojego prototypu (jak getMethods() w Javie). Jeśli chcesz zobaczyć tylko te metody zdefiniowane bezpośrednio przez obj, możesz sprawdzić za pomocą hasOwnProperty:

var methods = [];
for (var m in obj) {        
    if (typeof obj[m] == "function" && obj.hasOwnProperty(m)) {
        methods.push(m);
    }
}
alert(methods.join(","));
 60
Author: Roland Bouman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-13 15:15:50

Najnowocześniejsza obsługa przeglądarki console.dir(obj), która zwróci wszystkie właściwości obiektu odziedziczone przez jego konstruktor. Więcej informacji i aktualna obsługa przeglądarki można znaleźć w dokumentacji Mozilli .

console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object
 31
Author: Geoff Moller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-04 16:10:08

Inne odpowiedzi tutaj działają na coś takiego jak matematyka, która jest obiektem statycznym. Ale nie działają one dla instancji obiektu, takiego jak data. Znalazłem następujące do pracy:

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/

To nie zadziała na coś podobnego do oryginalnego pytania (Matematyka), więc wybierz rozwiązanie na podstawie swoich potrzeb. Zamieszczam to tutaj, ponieważ Google wysłał mnie na to pytanie, ale chciałem wiedzieć, jak to zrobić na przykład przedmiotów.

 6
Author: Kip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-26 15:53:16

Krótka odpowiedź brzmi: nie możesz, ponieważ Math i Date (poza czubkiem mojej głowy, jestem pewien, że są inne) nie są normalnymi obiektami. Aby to zobaczyć, Utwórz prosty skrypt testowy:

<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>

Widzisz, że prezentuje się jako obiekt tak samo jak dokument, ale kiedy próbujesz zobaczyć w tym obiekcie, widzisz, że jest to rodzimy kod i coś, co nie jest wystawione w ten sam sposób do wyliczenia.

 3
Author: Nick Craver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-13 15:42:27

Math posiada statyczną metodę, w której można wywołać bezpośrednio jak Math.abs(), podczas gdy Date mA statyczną metodę jak Date.now(), a także metodę instancji, w której należy najpierw utworzyć nową instancję var time = new Date(), aby wywołać time.getHours().

// The instance method of Date can be found on `Date.prototype` so you can just call:
var keys = Object.getOwnPropertyNames(Date.prototype);

// And for the static method
var keys = Object.getOwnPropertyNames(Date);

// But if the instance already created you need to
// pass its constructor
var time = new Date();
var staticKeys = Object.getOwnPropertyNames(time.constructor);
var instanceKeys = Object.getOwnPropertyNames(time.constructor.prototype);

Oczywiście będziesz musiał filtrować uzyskane klucze dla metody statycznej, aby uzyskać rzeczywiste nazwy metod, ponieważ możesz również uzyskać length, name, które nie są funkcją na liście.

Ale jak jeśli chcemy uzyskać wszystkie dostępne metody z klasy, która rozszerza inny zajęcia?
oczywiście będziesz musiał przeskanować rdzeń prototypu, jak używając __proto__. Aby zaoszczędzić czas, możesz użyć skryptu poniżej, aby uzyskać statyczną metodę i głęboką instancję metody.

// var keys = new Set();
function getStaticMethods(keys, clas){
    var keys2 = Object.getOwnPropertyNames(clas);

    for(var i = 0; i < keys2.length; i++){
        if(clas[keys2[i]].constructor === Function)
            keys.add(keys2[i]);
    }
}

function getPrototypeMethods(keys, clas){
    if(clas.prototype === void 0)
        return;

    var keys2 = Object.getOwnPropertyNames(clas.prototype);
    for (var i = keys2.length - 1; i >= 0; i--) {
        if(keys2[i] !== 'constructor')
            keys.add(keys2[i]);
    }

    var deep = Object.getPrototypeOf(clas);
    if(deep.prototype !== void 0)
        getPrototypeMethods(keys, deep);
}

// ====== Usage example ======
// To avoid duplicate on deeper prototype we use `Set`
var keys = new Set();
getStaticMethods(keys, Date);
getPrototypeMethods(keys, Date);

console.log(Array.from(keys));

Jeśli chcesz uzyskać metody z utworzonej instancji, nie zapomnij przekazać jej constructor.

 1
Author: StefansArya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-09 18:15:17

Wierzę, że jest prosty historyczny powód, dla którego nie można wyliczyć nad metodami obiektów wbudowanych, np. Array. Oto dlaczego:

Metody są właściwościami prototype-object, powiedzmy Object.prototyp. Oznacza to, że wszystkie instancje obiektu będą dziedziczyć te metody. To dlaczego można używać tych metod na dowolnym obiekcie. Powiedz .na przykład toString ().

Więc gdyby metody były wyliczalne, a iterowałbym nad say {a: 123} with: "for (key in {a: 123}) {..."co co by się stało? Ile razy czy ta pętla zostanie wykonana?

Zostanie powtórzona raz dla pojedynczego klucza 'a' w naszym przykładzie. ALE TAKŻE jeden raz na każdą wartość właściwości obiektu.prototyp. Więc jeśli metody były wyliczalne (domyślnie), wtedy każda pętla nad dowolnym obiektem będzie pętla nad wszystkimi metodami dziedziczenia.

 0
Author: Panu Logic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-26 19:55:30