Какой самый быстрый способ подсчитать количество ключей / свойств объекта? Можно ли сделать это без перебора объекта? т.е. без выполнения
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox действительно предоставлял магическое __count__
свойство, но это было удалено где-то в версии 4.)
Ответы:
Чтобы сделать это в любой ES5-совместимой среде , такой как Node , Chrome, IE 9+, Firefox 4+ или Safari 5+:
источник
Вы можете использовать этот код:
Затем вы можете использовать это в старых браузерах:
источник
(Object.prototype.hasOwnProperty.call(obj, k))
?hasOwnProperty
необходима. Он возвращает только свойства, установленные для самого объекта.obj.hasOwnProperty(k)
(я действительно сделал это в своем первоначальном сообщении, но обновил его позже).hasOwnProperty
доступен для каждого объекта, потому что он является частьюObject
прототипа, но в редких случаях, когда этот метод будет удален или переопределен, вы можете получить неожиданные результаты. Вызов его изObject.prototype
него делает его немного более надежным. Причина использованияcall
заключается в том, что вы хотите вызывать методobj
вместо прототипа.Если вы используете Underscore.js, вы можете использовать _.size (спасибо @douwe):
_.size(obj)
В качестве альтернативы вы также можете использовать _.keys, которые могут быть более понятными для некоторых:
_.keys(obj).length
Я настоятельно рекомендую Underscore, его компактную библиотеку для выполнения множества базовых задач. По мере возможности они соответствуют ECMA5 и относятся к собственной реализации.
В противном случае я поддерживаю ответ @ Avi. Я отредактировал его, чтобы добавить ссылку на документ MDC, который включает метод keys (), который можно добавить в браузеры не ECMA5.
источник
_.keys(obj).length
работал лучше всего для меня, потому что мой возвращаемый объект иногда представляет собой простую строку без каких-либо свойств внутри него._.size(obj)
возвращает мне длину строки, а_.keys(obj).length
возвращает 0.Object.keys
внутри. Подчеркивание также копирует каждый ключ в массив внутриfor..in
цикла, еслиObject.keys
он не определен.Стандартная реализация объекта ( ES5.1 «Внутренние свойства и методы объекта» ) не требует
Object
отслеживания количества ключей / свойств, поэтому не должно быть стандартного способа определения размераObject
без явной или неявной итерации его ключей.Итак, вот наиболее часто используемые альтернативы:
1. ECMAScript Object.keys ()
Object.keys(obj).length;
Работает путем внутренней перебора ключей для вычисления временного массива и возвращает его длину.2. Библиотечные решения
Многие основанные на библиотеках примеры в других разделах этой темы являются полезными идиомами в контексте их библиотеки. Однако с точки зрения производительности выиграть нечего по сравнению с идеальным кодом без библиотеки, поскольку все эти библиотечные методы на самом деле инкапсулируют либо цикл for, либо ES5
Object.keys
(нативный или отстраненный).3. Оптимизация цикла for
Самая медленная часть такого цикла for - это обычно
.hasOwnProperty()
вызов из-за накладных расходов на вызов функции. Поэтому, когда мне просто нужно количество записей в объекте JSON, я просто пропускаю.hasOwnProperty()
вызов, если знаю, что ни один код не расширялся и не будет расширятьсяObject.prototype
.В противном случае ваш код можно было бы немного оптимизировать, сделав
k
local (var k
) и используя префикс-инкремент оператора (++count
) вместо постфикса.Другая идея основана на кэшировании
hasOwnProperty
метода:Является ли это быстрее или нет в данной среде - это вопрос сравнительного анализа. В любом случае можно ожидать очень ограниченного прироста производительности.
источник
var k in myobj
повысить производительность? Насколько я знаю, только функции объявляют новую область видимости в JavaScript. Являются ли in-loop исключением из этого правила?for (var k in myobj) hasOwn.call(myobj, k) && ++count;
т.е. заменяя оператор if простым &&?Object.getOwnPropertyNames(obj).length
:; намного прощеЕсли вы действительно столкнулись с проблемой производительности, я бы предложил обернуть вызовы, которые добавляют / удаляют свойства к / из объекта, с функцией, которая также увеличивает / уменьшает свойство с соответствующим именем (size?).
Вам нужно только рассчитать начальное количество свойств один раз и двигаться дальше. Если нет реальной проблемы с производительностью, не беспокойтесь. Просто оберните этот фрагмент кода в функцию
getNumberOfProperties(object)
и покончите с этим.источник
Как заявил Ави Лен https://stackoverflow.com/a/4889658/1047014
будет делать трюк для всех перечисляемых свойств вашего объекта, но также включать неперечислимые свойства, которые вы можете вместо этого использовать
Object.getOwnPropertyNames
. Вот разница:Как указано здесь, он имеет ту же поддержку браузера, что и
Object.keys
Тем не менее, в большинстве случаев, вы можете не захотеть включать не перечисляемые в этот тип операций, но всегда полезно знать разницу;)
источник
Object.getOwnPropertyNames
, вы были здесь единственным ...Я не знаю ни одного способа сделать это, однако, чтобы свести итерации к минимуму, вы можете попробовать проверить наличие
__count__
и, если он не существует (то есть не Firefox), то вы можете перебрать объект и определить это для последующего использования, например:Таким образом, любой поддерживающий браузер
__count__
будет использовать это, и итерации будут выполняться только для тех, которые этого не делают. Если счетчик меняется и вы не можете этого сделать, вы всегда можете сделать его функцией:Таким образом, в любое время вы ссылаетесь на myobj.
__count__
функция сработает и пересчитает.источник
Object.prototype.__count__
что в Gecko 1.9.3 удаляется : whereswalden.com/2010/04/06/… count -property -of-objects-is-Object.__count__
ушел, и хорошее избавление тоже.Итерации по Avi Flax ответ Object.keys (obj) .length правильно для объекта, к которому не привязаны функции
пример:
против
шаги, чтобы избежать этого:
не помещайте функции в объект, который вы хотите посчитать количество ключей в
используйте отдельный объект или создайте новый объект специально для функций (если вы хотите подсчитать, сколько функций используется в файле
Object.keys(obj).length
)также да, я использовал _ или модуль подчеркивания из nodejs в моем примере
документацию можно найти здесь http://underscorejs.org/, а также ее источник на github и другую другую информацию
И, наконец, реализация lodash https://lodash.com/docs#size
_.size(obj)
источник
Array(obj).length
: Это не работает. http://jsfiddle.net/Jhy8M/false
, хотя я еще не нашел никакой документации о том, какvar obj = { a: true, b: true }
может отличатьсяvar obj = {}; obj.a = true; obj.b = true;
или просто если другая интерпретация / семантика W3 имеет был принят Chrome.как ответили выше:
Object.keys(obj).length
Но: поскольку у нас теперь есть реальный класс Map в ES6, я бы предложил использовать его вместо использования свойств объекта.
источник
Для тех, у кого есть Underscore.js, включенный в их проект, вы можете сделать:
или функциональный стиль:
источник
Вот несколько тестов производительности для трех методов;
https://jsperf.com/get-the-number-of-keys-in-an-object
Object.keys (). Длина
20 735 операций в секунду
Очень просто и совместимо. Работает быстро, но дорого, потому что создает новый массив ключей, который затем отбрасывается.
перебрать ключи
15 734 операций в секунду
Немного медленнее, но не близко к использованию памяти, поэтому, вероятно, лучше, если вы заинтересованы в оптимизации для мобильных или других небольших машин
Использование карты вместо объекта
953 839 338 операций в секунду
По сути, Map отслеживает свой собственный размер, поэтому мы просто возвращаем числовое поле. Гораздо быстрее, чем любой другой метод. Если у вас есть контроль над объектом, вместо этого конвертируйте их в карты.
источник
От: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Вы можете добавить его ко всем вашим объектам:
Или один объект:
Пример:
Добавленный таким образом, он не будет отображаться в циклах for..in:
Вывод:
Примечание: он не работает в браузерах <IE9.
источник
Я решил эту проблему, создав собственную реализацию базового списка, который хранит записи о том, сколько элементов хранится в объекте. Это очень просто. Что-то вроде этого:
источник
var i = basiclist.count
while(i--){...}
add
заменяет ли старый элемент илиremove
вызывается с несуществующим индексом. Также невозможно проверить, имеет ли список заданный индекс, еслиundefined
является допустимым значением элемента.Вы можете использовать,
Object.keys(data).length
чтобы найти длину объекта JSON, имеющего ключевые данныеисточник
Для тех, кто имеет Ext JS 4 в своем проекте, вы можете сделать:
Преимущество этого состоит в том, что он будет работать во всех совместимых с Ext браузерах (включая IE6-IE8), однако, я считаю, что время выполнения не лучше, чем O (n), как и в других предлагаемых решениях.
источник
Ты можешь использовать:
а также
источник
OP не указал, является ли объект нодлистом, если это так, то вы можете просто использовать метод длины непосредственно для него. Пример:
источник
Если jQuery выше не работает, то попробуйте
источник
Object.Item
не существуетЯ не думаю, что это возможно (по крайней мере, без использования некоторых внутренних). И я не думаю, что вы бы много выиграли, оптимизировав это.
источник
Я пытаюсь сделать его доступным для всех объектов следующим образом:
источник
У Google Closure есть хорошая функция для этого ... goog.object.getCount (obj)
посмотрите на goog. Объектная документация
источник