Я хочу знать, как перечислить все методы, доступные для объекта, например:
alert(show_all_methods(Math));
Это должно напечатать:
abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
Я хочу знать, как перечислить все методы, доступные для объекта, например:
alert(show_all_methods(Math));
Это должно напечатать:
abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
Ответы:
Вы можете использовать, 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, сообщил{ DontEnum }
мне об ошибке IE .
Вместо проверки атрибута DontEnum, [Microsoft] JScript пропустит любое свойство в любом объекте, где есть свойство с таким же именем в цепочке прототипов объекта, которая имеет атрибут DontEnum.
Короче, будьте осторожны при именовании свойств вашего объекта. Если есть встроенное свойство прототипа или метод с тем же именем, то IE пропустит его при использовании for...in
цикла.
Object.getOwnPropertyNames()
, что будет возвращать даже не перечисляемые свойства и методы.
Object.getOwnPropertyNames(Array.prototype)
?
С 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));
логи ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]
в произвольном порядке.
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(","));
document
или window
я получаю больше удачи. Честно говоря, это немного неожиданно, я не знаю, почему это не работает для математики и т. Д.
document
и window
являются объектами с перечисляемыми свойствами, предоставляемыми браузером, они не являются частью среды выполнения сценариев. Нативные объекты есть и, очевидно, свойства не перечисляются.
Поддержка большинства современных браузеров console.dir(obj)
, которая возвращает все свойства объекта, которые он унаследовал через конструктор. См. Документацию Mozilla для получения дополнительной информации и текущей поддержки браузера.
console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object
Другие ответы здесь работают для чего-то вроде 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/
Это не сработает для чего-то вроде оригинального вопроса (Math), поэтому выбирайте свое решение исходя из своих потребностей. Я публикую это здесь, потому что Google отправил меня на этот вопрос, но я хотел знать, как это сделать для экземпляров объектов.
Короткий ответ: ты не можешь, потому что ( Math
и Date
я уверен, что есть и другие) не являются нормальными объектами. Чтобы увидеть это, создайте простой тестовый скрипт:
<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>
Вы видите, что он представлен как объект точно так же, как документ в целом, но когда вы на самом деле пытаетесь увидеть этот объект, вы видите, что это нативный код и что-то, что не перечислено для перечисления таким же образом.
Math
имеет статический метод, где вы можете вызывать напрямую, как в Math.abs()
то время как Date
имеет статический метод как, Date.now()
а также метод экземпляра, где вам нужно сначала создать новый экземпляр var time = new Date()
для вызова 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);
Конечно, вам нужно будет отфильтровать полученные ключи для статического метода, чтобы получить реальные имена методов, потому что вы также можете получить length, name
те, которые не являются функцией в списке.
Но как, если мы хотим получить все доступные методы из класса, которые расширяют другой класс?
Конечно, вам нужно будет сканировать корень прототипа, как при использовании __proto__
. Для экономии вашего времени вы можете использовать скрипт ниже, чтобы получить статический метод и глубокий экземпляр метода.
// 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));
Если вы хотите получить методы из созданного экземпляра, не забудьте передать constructor
его.
Я полагаю, что существует простая историческая причина, по которой вы не можете перечислять методы встроенных объектов, таких как, например, Array. Вот почему:
Методы - это свойства объекта-прототипа, скажем, Object.prototype. Это означает, что все экземпляры Object будут наследовать эти методы. Вот почему вы можете использовать эти методы на любом объекте. Скажем .toString (), например.
Так что методы IF были перечислимы, и я бы повторил, скажем, {a: 123} с помощью: "for (введите {a: 123}) {...}" что произойдет? Сколько раз этот цикл будет выполнен?
В нашем примере это будет повторено один раз для единственного ключа «а». НО ТАКЖЕ один раз для каждого перечисляемого свойства Object.prototype. Таким образом, если бы методы были перечисляемыми (по умолчанию), то любой цикл по любому объекту также должен был бы пройти по всем его унаследованным методам.
Object.getOwnPropertyNames(Array.prototype)
например,