Я хочу знати, як перелічити всі доступні для об’єкта методи, наприклад, наприклад:
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)
наприклад