Скажем, я создаю объект таким образом:
var myObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
Как лучше всего получить список имен свойств? то есть я хотел бы получить некоторые переменные 'ключи', такие как:
keys == ["ircEvent", "method", "regex"]
Object.keys(obj) Sometimes you want non-enumerable properties as well. Make sure to remember this if you do! To get them, use Object.getOwnPropertyNames(obj)stackoverflow.com/a/32413145/1599699


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В современных браузерах (IE9 +, FF4 +, Chrome5 +, Opera12 +, Safari5 +) вы можете использовать встроенный метод Object.keys:
var keys = Object.keys(myObject);
В приведенном выше примере есть полный полифилл, но упрощенная версия:
var getKeys = function(obj){
var keys = [];
for(var key in obj){
keys.push(key);
}
return keys;
}
В качестве альтернативы замените var getKeys на Object.prototype.keys, чтобы вы могли вызывать .keys() для любого объекта. Расширение прототипа имеет некоторые побочные эффекты, и я бы не рекомендовал это делать.
Я бы снова обновился, сказав, что «у вас может возникнуть соблазн сделать это с прототипом объекта ... но не делайте этого!»
кто-нибудь захочет пролить свет, почему не рекомендуется добавлять функции в прототип объекта?
Это совсем другой вопрос сам по себе, быстрый поиск здесь в stackoverflow или в google даст вам много, чтобы прочитать
Я пробовал это в Google Chrome 27: вы можете просто использовать keys(myJsonObject), не ссылаясь на Object.
Метод for (var key in myObject) {...} полезен для среды выполнения javascript вне браузеров и V8. Например, при передаче запросов javascript map-reduce в Riak объект Object не существует, поэтому метод Object.keys недоступен.
полифил намного быстрее. jsperf.com/listing-javascript-properties
Object.keys() в ECMA 5.1. В ближайшее время он будет доступен где угодно!
@slashnick Ваша «упрощенная версия» возвращает все свойства в цепочке прототипов объекта (поскольку она использует «for ... in»), тогда как метод (ECMAScript 5.1) Object.keys возвращает только собственные свойства объекта. Я считаю это важным отличием.
Я согласен с @MartinCarel. На мой взгляд, ответ следует отредактировать, чтобы отфильтровать свойства с помощью hasOwnProperty (поскольку это упрощенная версия, вероятно, не нужно включать обходной путь ошибки перечисления). Это в основном то, что задает исходный вопрос (контекстуально), и что делает фактическая функция Object.keys.
Как указывает слэшник, вы можете использовать конструкцию «for in» для итерации по объекту для его имен атрибутов. Однако вы будете перебирать все имена атрибутов в цепочке прототипов объекта. Если вы хотите выполнить итерацию Только по собственным атрибутам объекта, вы можете использовать метод Объект # hasOwnProperty (). Таким образом имея следующее.
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
/* useful code here */
}
}
Мне жаль, что я не прочитал это до ответа Слэшника выше. Мне просто пришлось потратить 15 минут, удерживая клавишу esc, потому что у объекта было около миллиона свойств, большинство из которых не использовались, и у меня было предупреждение.
Вот отличная статья на эту тему самого Закаса: nczonline.net/blog/2010/07/27/…
LOL @MarkHenderson - но в следующий раз просто закройте процесс браузера и перезапустите его вместо того, чтобы тратить 15 минут :)
Связанная функция - obj.getOwnPropertyNames () - developer.mozilla.org/en-US/docs/JavaScript/Reference/…
@MarkHenderson Почему вы не используете console.info?
Красиво, надо было обновить выбранный ответ этим вместо того, чтобы добавлять новый.
IE не поддерживает (i in obj) для собственных свойств. Вот список всего реквизита, который я смог найти.
Кажется, stackoverflow выполняет глупую фильтрацию.
Список доступен внизу этого сообщения группы Google: - https://groups.google.com/group/hackvertor/browse_thread/thread/a9ba81ca642a63e0
Я большой поклонник функции дампа.
http://ajaxian.com/archives/javascript-variable-dump-in-coldfusion
+1 потому что я попал сюда с намерением построить нечто подобное (хотя и не такое хорошее).
@Kiquenet каждый раз, когда я хотел создать что-то подобное, я соглашался на обычный инспектор объектов, если вы хотите, чтобы это отображалось в HTML, есть такие вещи, как модули npm. Честно говоря, я застрял в том, что я хотел чего-то лучшего, чем то, что изображено на этом изображении, но так и не смог концептуализировать это. Дерьмово просматривать объекты в инспекторе, но эвристика, пытающаяся вывести значение из произвольных объектов (например, сортировка массивов объектов по таблицам со столбцами), не всегда работает на практике.
Что насчет Довольно печатный Javascripthttps://j11y.io/demos/prettyprint/?
Обратите внимание, что Object.keys и другие методы ECMAScript 5 поддерживаются Firefox 4, Chrome 6, Safari 5, IE 9 и выше.
Например:
var o = {"foo": 1, "bar": 2};
alert(Object.keys(o));
Таблица совместимости ECMAScript 5: http://kangax.github.com/es5-compat-table/
Описание новых методов: http://markcaudill.com/index.php/2009/04/javascript-new-features-ecma5/
Также проверьте ключи () в консоли для Chrome Dev Tools, Firebug и т. д.
Как ответил Сэм Даттон, в ECMAScript 5th Edition появился новый метод именно для этой цели. Object.keys() будет делать то, что вы хотите, и поддерживается в Firefox 4, Chrome 6, Safari 5 и IE 9.
Вы также можете очень легко реализовать метод в браузерах, которые его не поддерживают. Однако некоторые реализации не полностью совместимы с Internet Explorer. Вот более совместимое решение:
Object.keys = Object.keys || (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
DontEnums = [
'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
],
DontEnumsLength = DontEnums.length;
return function (o) {
if (typeof o != "object" && typeof o != "function" || o === null)
throw new TypeError("Object.keys called on a non-object");
var result = [];
for (var name in o) {
if (hasOwnProperty.call(o, name))
result.push(name);
}
if (hasDontEnumBug) {
for (var i = 0; i < DontEnumsLength; i++) {
if (hasOwnProperty.call(o, DontEnums[i]))
result.push(DontEnums[i]);
}
}
return result;
};
})();
Обратите внимание, что принятый в настоящее время ответ не включает проверку hasOwnProperty () и возвращает свойства, которые наследуются через цепочку прототипов. Он также не учитывает известную ошибку DontEnum в Internet Explorer, когда неперечислимые свойства в цепочке прототипов заставляют локально объявленные свойства с тем же именем наследовать свой атрибут DontEnum.
Реализация Object.keys () даст вам более надежное решение.
Обновлено: после недавнего обсуждения с Кангакс, хорошо известным участником Prototype, я реализовал обходной путь для ошибки DontEnum на основе кода для его функции Object.forIn(), найденной здесь.
Отличный ответ, я думаю, что принятый ответ остается наиболее эффективным точным решением, если предположить, что это всегда JSON dict. Это, безусловно, тот, который можно использовать в другом месте.
@David Caunt: Спасибо :-) К сожалению, принятый ответ все равно не соответствует ошибке DontEnum, и вы никогда не знаете, какой объект JSON может иметь строку типа «valueOf» или «constructor» в качестве одного из ключей. Он также будет повторять расширения Object.prototype. Однако часто бывает, что более короткий код выглядит значительно более привлекательным, чем более крупный и надежный код, но суть этого ответа заключается в использовании ECMAScript 5th Object.keys(), который может быть реализован в браузерах, которые не поддерживают его с помощью этого кода. Родная версия была бы даже более производительной, чем эта.
Хороший момент - вы правы насчет ошибки. Я надеюсь, что любой хороший разработчик протестирует нативные методы перед использованием своих собственных реализаций.
Очень мило, Энди :) Я просто хотел бы напомнить - никто, кажется, не упоминает в этой теме - что ES5 Object.keys возвращает только массив строк, соответствующих свойствам перечислимый объекта. Это может не иметь решающего значения при работе с собственными (определяемыми пользователем) объектами, но должно быть очень хорошо видно для узловых объектов (хотя поведение неопределенных узловых объектов - это отдельная - болезненная - история). Для перечисления по ВСЕМ (включая неперечислимые) свойства ES5 предоставляет Object.getOwnPropertyNames (см. Его поддержку в моей таблице совместимости - kangax.github.com/es5-compat-table)
Я интегрировал это решение в es5-shim github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L390
@Kris: это здорово, спасибо за указание :-) @kangax: да, это определенно стоит упомянуть и просто напомнило мне о фрагменте кода, который мне нужно обновить, спасибо :-)
Конечно, это все еще работает только для Object. Если бы вы сделали что-то глупое, например, поместили свойство затенения getFullYear в экземпляр Date, это все равно не сделало бы это перечислимым. Чтобы обойти это, вам нужно иметь гораздо более длинный список всех собственных свойств IE <9 и проверять каждое с помощью hasOwnProperty и propertyIsEnumerable. Не очень весело.
@bobince: правда, не так уж и весело! Надеюсь, это поможет нам, пока IE <9 не станет далеким воспоминанием :-)
Может кто-нибудь объяснить, почему это реализовано как Object.keys(stuff), а не stuff.keys()?
@ mblase75: вместо того, чтобы объяснять это здесь, вы можете прочитать обсуждение этого в списке рассылки es-Disc, начиная с здесь.
@Kiquenet: да, к сожалению, блог потерялся для эфира, когда я оставил предыдущую работу, которая включала хостинг ... извините за это!
если вы пытаетесь получить только элементы, но не функции, этот код может вам помочь
this.getKeys = function() {
var keys = new Array();
for(var key in this) {
if ( typeof this[key] !== 'function') {
keys.push(key);
}
}
return keys;
}
это часть моей реализации HashMap, и мне нужны только ключи, "this" - это объект hashmap, который содержит ключи
Это будет работать в большинстве браузеров, даже в IE8, и никаких библиотек не требуется. var i - ваш ключ.
var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
var keys=[];
for (var i in myJSONObject ) { keys.push(i); }
alert(keys);
Ваш ответ похож на уже опубликованный, что еще добавить?
В браузерах, поддерживающих js 1.8:
[i for(i in obj)]
Можно было сделать это с помощью jQuery следующим образом:
var objectKeys = $.map(object, function(value, key) {
return key;
});
В Mozilla есть полная информация о реализации о том, как это сделать в браузере, где он не поддерживается, если это помогает:
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [];
for (var prop in obj) {
if (hasOwnProperty.call(obj, prop)) result.push(prop);
}
if (hasDontEnumBug) {
for (var i=0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
}
}
return result;
};
})();
}
Вы можете включить его, как хотите, но, возможно, в какой-то файл extensions.js наверху вашего стека скриптов.
Реализация MDN основана на Andy E's, которое уже было дано в качестве ответа.
Основываясь на принятом ответе.
Если у объекта есть свойства, которые вы хотите вызвать, скажем .properties () попробуйте!
var keys = Object.keys(myJSONObject);
for (var j=0; j < keys.length; j++) {
Object[keys[j]].properties();
}
Поскольку я использую underscore.js почти в каждом проекте, я бы использовал функцию keys:
var obj = {name: 'gach', hello: 'world'};
console.info(_.keys(obj));
Результатом этого будет:
['name', 'hello']
Это библиотека набора инструментов для часто используемых функций javascript: underscorejs.org
Object.getOwnPropertyNames(obj)
Эта функция также показывает неперечислимые свойства в дополнение к свойствам, показанным Object.keys(obj).
В JS каждое свойство имеет несколько свойств, включая логическое значение enumerable.
В общем, неперечислимые свойства являются более «внутренними» и используются реже, но иногда полезно изучить их, чтобы увидеть, что происходит на самом деле.
Пример:
var o = Object.create({base:0})
Object.defineProperty(o, 'yes', {enumerable: true})
Object.defineProperty(o, 'not', {enumerable: false})
console.info(Object.getOwnPropertyNames(o))
// [ 'yes', 'not' ]
console.info(Object.keys(o))
// [ 'yes' ]
for (var x in o)
console.info(x)
// yes, base
Также обратите внимание, как:
Object.getOwnPropertyNames и Object.keysне идут вверх по цепочке прототипов, чтобы найти base.for in делаетПодробнее о цепочке прототипов здесь: https://stackoverflow.com/a/23877420/895245
Решение работает на моих кейсах и кроссбраузерно:
var getKeys = function(obj) {
var type = typeof obj;
var isObjectType = type === 'function' || type === 'object' || !!obj;
// 1
if (isObjectType) {
return Object.keys(obj);
}
// 2
var keys = [];
for(var i in obj) {
if (obj.hasOwnProperty(i)) {
keys.push(i)
}
}
if (keys.length) {
return keys;
}
// 3 - bug for ie9 <
var hasEnumbug = !{toString: null}.propertyIsEnumerable('toString');
if (hasEnumbug) {
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
var nonEnumIdx = nonEnumerableProps.length;
while (nonEnumIdx--) {
var prop = nonEnumerableProps[nonEnumIdx];
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
keys.push(prop);
}
}
}
return keys;
};
Используйте Reflect.ownKeys()
var obj = {a: 1, b: 2, c: 3};
Reflect.ownKeys(obj) // ["a", "b", "c"]
Object.keys и Object.getOwnPropertyNames не могут получить свойства не перечислимый. Работает даже для свойств не перечислимый.
var obj = {a: 1, b: 2, c: 3};
obj[Symbol()] = 4;
Reflect.ownKeys(obj) // ["a", "b", "c", Symbol()]
В ES6 и более поздних версиях (ECMAScript 2015) вы можете получить все свойства, подобные этому:
let keys = Object.keys(myObject);
И если вы хотите перечислить все значения:
let values = Object.keys(myObject).map(key => myObject[key]);
Немного не по теме, но если вы используете underscore.js:
_.keys(myJSONObject)