Как эффективно подсчитать количество ключей / свойств объекта в JavaScript?
каков самый быстрый способ подсчета количества ключей / свойств объекта? Можно ли это сделать без итерации по объекту? т. е. не делая
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox действительно предоставил волшебство __count__ свойство, но это было удалено где-то около версии 4.)
19 ответов:
чтобы сделать это в любой ES5-совместимой среде, например узел, Chrome, IE 9+, FF 4+ или Safari 5+:
Object.keys(obj).length
Вы можете использовать этот код:
if (!Object.keys) { Object.keys = function (obj) { var keys = [], k; for (k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } } return keys; }; }тогда вы можете использовать это и в старых браузерах:
var len = Object.keys(obj).length;
Если вы используете подчеркивания.js можно использовать _.размер (спасибо @douwe):
_.size(obj)в качестве альтернативы вы можете также использовать _.ключи что может быть понятнее для некоторых:
_.keys(obj).lengthя настоятельно рекомендую подчеркивание, его плотная библиотека для выполнения множества основных вещей. По возможности они соответствуют ECMA5 и относятся к собственной реализации.
в противном случае я поддерживаю ответ @Avi. Я отредактировал его, чтобы добавить ссылка на документ MDC, который включает метод keys (), который вы можете добавить в браузеры, отличные от ECMA5.
реализация стандартного объекта (ES5. 1 внутренние свойства и методы объекта) не требует
Objectчтобы отслеживать его количество ключей / свойств, поэтому не должно быть стандартного способа определить размерObjectбез явного или неявного перебора его ключей.Итак, вот наиболее часто используемые варианты:
1. Объект ECMAScript.ключи()
Object.keys(obj).length;произведения внутри итерация по ключам для вычисления временного массива и возвращает его длину.
- плюсы - читаемый и чистый синтаксис. Никакая библиотека или пользовательский код не требуется, кроме прокладки, если собственная поддержка недоступна
- минусы - накладные расходы памяти из-за создания массива.
2. Библиотека на основе решений
многие примеры на основе библиотек в других местах этого раздела являются полезными идиомами в контексте их библиотека. Однако с точки зрения производительности нет ничего, что можно было бы получить по сравнению с идеальным кодом без библиотеки, поскольку все эти методы библиотеки фактически инкапсулируют либо цикл for, либо ES5
Object.keys(родной или shimmed).3. Оптимизация цикла for
The медленная часть такого for-цикла, как правило,
.hasOwnProperty()вызов, из-за накладных расходов вызова функции. Поэтому, когда мне просто нужно количество записей объекта JSON, я просто пропускаю.hasOwnProperty()звоните, если я знаю, что ни один код не сделал и не будет расширятьсяObject.prototype.в противном случае, ваш код может быть слегка оптимизирован путем внесения
klocal (var k) и с помощью оператора префикс-инкремент (++count), а не постфикс.var count = 0; for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;другая идея опирается на кэширование
hasOwnPropertyспособ:var hasOwn = Object.prototype.hasOwnProperty; var count = 0; for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;является ли это быстрее или нет в данной среде-это вопрос бенчмаркинга. Очень ограниченный прирост производительности можно ожидать в любом случае.
Если вы действительно столкнулись с проблемой производительности, я бы предложил обернуть вызовы, которые добавляют / удаляют свойства в / из объекта с помощью функции, которая также увеличивает / уменьшает соответствующее имя (размер?) свойство.
вам нужно только вычислить начальное количество свойств один раз и двигаться дальше оттуда. Если нет реальной проблемы производительности, не беспокойтесь. Просто оберните этот бит кода в функцию
getNumberOfProperties(object)и покончим с этим.
Я не знаю, как это сделать, однако, чтобы свести итерации к минимуму, вы можете попробовать проверить наличие
__count__и если он не существует (т. е. не Firefox), то вы можете перебирать объект и определять его для последующего использования, например:if (myobj.__count__ === undefined) { myobj.__count__ = ... }таким образом, любой браузер, поддерживающий
__count__будет использовать это, и итерации будут проводиться только для тех, кто не. Если граф меняется и ты не можешь этого сделать, ты всегда можешь сделать это функция:if (myobj.__count__ === undefined) { myobj.__count__ = function() { return ... } myobj.__count__.toString = function() { return this(); } }таким образом, в любое время вы ссылаетесь на myobj.
__count__функция будет срабатывать и пересчитывать.
как заявил Ави лен https://stackoverflow.com/a/4889658/1047014
Object.keys(obj).lengthбудет делать трюк для всех перечислимых свойств на вашем объекте, но также включать не перечислимые свойства вы можете вместо этого использовать
Object.getOwnPropertyNames. Вот в чем разница:var myObject = new Object(); Object.defineProperty(myObject, "nonEnumerableProp", { enumerable: false }); Object.defineProperty(myObject, "enumerableProp", { enumerable: true }); console.log(Object.getOwnPropertyNames(myObject).length); //outputs 2 console.log(Object.keys(myObject).length); //outputs 1 console.log(myObject.hasOwnProperty("nonEnumerableProp")); //outputs true console.log(myObject.hasOwnProperty("enumerableProp")); //outputs true console.log("nonEnumerableProp" in myObject); //outputs true console.log("enumerableProp" in myObject); //outputs trueкак заявил здесь это имеет ту же поддержку браузера, что и
Object.keysоднако, в большинстве случаев, вы не можете включить nonenumerables в этот тип операций, но всегда хорошо знать разницу ;)
для итерации по объекту ответа avi Flax.ключи(объект).длина верна для объекта, который не имеет привязанных к нему функций
пример:
obj = {"lol": "what", owo: "pfft"}; Object.keys(obj).length; // should be 2и
arr = []; obj = {"lol": "what", owo: "pfft"}; obj.omg = function(){ _.each(obj, function(a){ arr.push(a); }); }; Object.keys(obj).length; // should be 3 because it looks like this /* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */шаги, чтобы избежать этого:
не помещайте функции в объект, который вы хотите подсчитать количество ключей в
используйте отдельный объект или создайте новый объект специально для функций (если вы хотите подсчитать, сколько функций есть в файле с помощью
Object.keys(obj).length)также Да я использовал модуль _ или подчеркивания из nodejs в моем примере
документация может быть найдена здесь http://underscorejs.org/ а также его источник на github и различные другие данные
и, наконец, реализация лодашь https://lodash.com/docs#size
_.size(obj)
для тех, у кого есть подчеркивание.js включены в их проект вы можете сделать:
_({a:'', b:''}).size() // => 2или функциональном стиле:
_.size({a:'', b:''}) // => 2
Как я решил эту проблему, чтобы построить свою собственную реализацию базового списка, который хранит запись о том, сколько элементов хранятся в объекте. Это очень просто. Что-то вроде этого:
function BasicList() { var items = {}; this.count = 0; this.add = function(index, item) { items[index] = item; this.count++; } this.remove = function (index) { delete items[index]; this.count--; } this.get = function(index) { if (undefined === index) return items; else return items[index]; } }
для тех, кто имеет Ext JS 4 в своем проекте вы можете сделать:
Ext.Object.getSize(myobj);преимущество этого заключается в том, что он будет работать на всех Ext совместимых браузерах (IE6-IE8 включены), однако, я считаю, что время работы не лучше, чем O(n), хотя, как и с другими предлагаемыми решениями.
Я не думаю, что это возможно (по крайней мере, не без некоторых внутренних органов). И я не думаю, что вы выиграете много, оптимизируя это.
Я пытаюсь сделать его доступным для всех объектов следующим образом:
Object.defineProperty(Object.prototype, "length", { get() { if (!Object.keys) { Object.keys = function (obj) { var keys = [],k; for (k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } } return keys; }; } return Object.keys(this).length; },}); console.log({"Name":"Joe","Age":26}.length) //returns 2
можно использовать
Object.keys(data).lengthчтобы найти длину объекта JSON, имеющего ключевые данные
Comments