Как отобразить все методы объекта?

Я хочу знать, как перечислять все доступные методы для объекта, например, например:

 alert(show_all_methods(Math));

Это должно печатать:

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

Ответ 1

Вы можете использовать Object.getOwnPropertyNames(), чтобы получить все свойства, принадлежащие объекту, независимо от того, перечислимы они или нет. Например:

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

Затем вы можете использовать filter(), чтобы получить только методы:

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

В браузерах ES3 (IE 8 и ниже) свойства встроенных объектов не перечислимы. Такие объекты, как window и document, не встроены, они определены браузером и, скорее всего, перечислимы по дизайну.

Из ECMA-262 Edition 3:

Глобальный объект
Существует уникальная глобальная объект (15.1), который создается до управление входит в любой контекст выполнения. Первоначально глобальный объект имеет следующие свойства:

• Встроенный объекты, такие как Math, String, Date, parseInt и т.д. Они имеют атрибуты { DontEnum}.
• Определен дополнительный хост свойства. Это может включать свойство, значение которого является глобальным сам объект; например, в HTML-объект модели объекта окна свойство глобального объекта является глобальный объект.

В качестве контроля входит в контексты выполнения и Выполняется код ECMAScript, дополнительные свойства могут быть добавлены к глобальный объект и начальный свойства могут быть изменены.

Я должен указать, что это означает, что эти объекты не являются перечисляемыми свойствами объекта Global. Если вы просмотрите остальную часть документа спецификации, вы увидите, что большинство встроенных свойств и методов этих объектов имеют атрибут { DontEnum }, установленный на них.


Обновление: пользователь SO, CMS, привёл IE-ошибку, касающуюся { DontEnum }, к моему вниманию.

Вместо проверки атрибута DontEnum, [Microsoft] JScript пропустит любое свойство в любом объекте, где в цепочке прототипов объекта есть свойство с одинаковым именем, которое имеет атрибут DontEnum.

Короче говоря, будьте осторожны при наименовании ваших свойств объекта. Если есть встроенное свойство прототипа или метод с тем же именем, то IE будет пропускать его при использовании цикла for...in.

Ответ 2

Это невозможно с ES3, поскольку свойства имеют внутренний атрибут DontEnum, который не позволяет нам перечислить эти свойства. ES5, с другой стороны, предоставляет дескрипторы свойств для управления возможностями перечисления свойств, поэтому пользовательские и собственные свойства могут использовать один и тот же интерфейс и пользоваться теми же возможностями, что и возможность программно отображать неперечислимые свойства.

Функция getOwnPropertyNames может использоваться для перечисления всех свойств переданного объекта, включая те, которые не перечислимы. Тогда простую проверку typeof можно использовать для отфильтровывания не-функций. К сожалению, Chrome - единственный браузер, в котором он работает в настоящее время.

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

console.log(getAllMethods(Math));

logs ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"] в определенном порядке.

Ответ 3

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

Таким образом вы получите все методы, которые вы можете вызвать obj. Это включает в себя методы, которые он "наследует" от своего прототипа (например, getMethods() в java). Если вы хотите видеть только те методы, которые определены непосредственно obj, вы можете проверить с помощью hasOwnProperty:

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

Ответ 4

Большинство современных браузеров поддерживают console.dir(obj), который возвращает все свойства объекта, которые он унаследовал через конструктор. См. Документацию Mozilla для получения дополнительной информации и текущей поддержки браузера.

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

Ответ 5

Короткий ответ: вы не можете, потому что Math и Date (с верхней части головы, я уверен, что есть другие), являются обычными объектами. Чтобы увидеть это, создайте простой тест script:

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

Вы видите, что он представляет объект как тот же самый способ, который делает документ в целом, но когда вы на самом деле пытаетесь видеть в этом объекте, вы видите, что его собственный код и что-то не показано одинаково для перечисления.

Ответ 6

Другие ответы здесь работают для чего-то вроде Math, который является статическим объектом. Но они не работают для экземпляра объекта, такого как дата. Я нашел следующее для работы:

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/

Это не сработает для чего-то вроде исходного вопроса (математика), поэтому выбирайте свое решение исходя из своих потребностей. Я публикую это здесь, потому что Google отправил меня на этот вопрос, но я хотел знать, как это сделать для экземпляров объектов.

Ответ 7

Я считаю, что есть простая историческая причина, почему вы не можете перечислить над методами таких встроенных объектов, как Array. Вот почему:

Способы - это свойства прототипа-объекта, например Object.prototype. Это означает, что все объекты-экземпляры наследуют эти методы. Это почему вы можете использовать эти методы для любого объекта. Например, скажем .toString().

Таким образом, методы IF были перечислимы, и я мог бы повторить использование {a: 123} с: "для (ключ в {a: 123}) {...}" что произойдет? Сколько раз будет ли этот цикл выполнен?

Он будет повторяться один раз для одного ключа "a" в нашем примере. НО ТАКЖЕ один раз для каждого перечислимого свойства Object.prototype. Так что если методы были перечислены (по умолчанию), тогда любой цикл над любым объектом будет циклическим над всеми его унаследованными методами.