Я хочу знати, як перелічити всі доступні для об’єкта методи, наприклад, наприклад:
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не вбудовані, вони визначаються браузером і, швидше за все, перераховані за дизайном.
Глобальний об'єкт
Існує унікальний глобальний об'єкт (15.1), який створюється до того, як контроль вступить у будь-який контекст виконання. Спочатку глобальний об'єкт має такі властивості:• Вбудовані об'єкти, такі як Math, String, Date, parseInt тощо. Вони мають атрибути {DontEnum} .
• Додаткові властивості, визначені хостом. Це може включати властивість, значенням якої є сам глобальний об'єкт; наприклад, в моделі об’єкта документа HTML властивістю вікна глобального об'єкта є сам глобальний об'єкт.Коли управління вводить контексти виконання, і коли виконується код ECMAScript, до глобального об'єкта можуть бути додані додаткові властивості, а початкові властивості можуть бути змінені.
Я мушу зазначити, що це означає, що ці об'єкти не перелічують властивості об'єкта Global. Якщо ви переглянете решту документа специфікації, ви побачите, що більшість вбудованих властивостей і методів цих об'єктів мають на них { DontEnum }атрибут.
Оновлення: інший користувач SO, CMS, звернув увагу на помилку IE{ DontEnum } .
Замість перевірки атрибута 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я отримую більше удачі. Відверто кажучи, це трохи несподівано, я не знаю, чому це не працює для Math і т. Д.
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. Це означає, що всі об'єкти-екземпляри успадкують ці методи. Ось чому ви можете використовувати ці методи на будь-якому об’єкті. Скажімо, наприклад, .toString ().
Тож методів ІЧ було безліч, і я хотів би повторити слово {a: 123} з: "for (введіть {a: 123}) {...}", що буде? Скільки разів ця петля буде виконана?
Був би повторений один раз для одного ключа 'a' у нашому прикладі. АЛЕ один раз для кожного перераховується майна Object.prototype. Отже, якщо методи були переліченими (за замовчуванням), то будь-який цикл над будь-яким об’єктом також би переходив на всі його успадковані методи.
Object.getOwnPropertyNames(Array.prototype)наприклад