Как эффективно подсчитать количество ключей/свойств объекта в JavaScript?

Какой самый быстрый способ подсчитать количество ключей/свойств объекта? Можно ли это сделать без итерации над объектом? Т.е. не делая

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;

(Firefox предоставлял волшебное свойство __count__, но оно было удалено где-то в четвертой версии).

Комментарии к вопросу (3)
Решение

Для этого в любом в ES5-совместимая среда, например, узел, хром, IE 9+ и выше, Firefox 4+, Safari или 5+:

Object.keys(obj).length
Комментарии (25)

Вы можете использовать этот код:

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;
Комментарии (12)

Если вы используете Underscore.js вы можете использовать _.размер (спасибо @его Douwe): _.размер(в obj)

В качестве альтернативы вы можете также использовать _.ключи что может быть понятнее для некоторых: `_.ключи(объект).длина

Я настоятельно рекомендую подчеркнуть, ее плотный библиотеки делают много элементарных вещей. По возможности они соответствовали ECMA5 и прислушивайтесь к собственной реализации.

В противном случае я поддерживаю @Ави'ы ответ. Я редактировал его, чтобы добавить ссылку в ЛДЦ док, который включает в себя ключи() способ вы можете добавить не ECMA5 браузерах.

Комментарии (7)

Стандартная реализация объекта (в ES5.1 объект внутренних свойств и методов) не требует объект, чтобы отслеживать его количество ключей/свойства, поэтому не должно быть никакого стандартного способа определить размер "объекта" без явно или неявно перебора ключей.

Итак, вот наиболее часто используемые варианты:

в

1. В ECMAScript's объекта.ключи()

Объект.ключи(объект).длина; работ внутренне перебирать ключи, чтобы вычислить временный массив и возвращает его длину.

  • Плюсы - четкий и ясный синтаксис. Нет библиотеки или пользовательский код не требуется, за исключением прокладку, если родной поддержки нет
  • Минусы - память, за счет создания массива.

2. Решения на базе библиотек

Многие библиотеки на основе примеров других в этом разделе находятся полезные идиомы в контексте их библиотека. С точки зрения производительности, однако, нет ничего, чтобы получить, по сравнению с идеальным нет-код библиотеки, так как все эти методы на самом деле инкапсулировать либо цикл for или объекта в ES5.ключи (родной или обертке).

3. Оптимизировать цикл for

В медленная часть такого цикла вообще .метод hasOwnProperty() вызов из-за вызова функции накладных расходов. Поэтому, когда я просто хотите, чтобы количество записей из объекта JSON, я просто пропустить .вызов метода hasOwnProperty() если я знаю, что никакой код не будет распространяться объект.прототип`.

В противном случае, ваш код может быть слегка оптимизирован, что делает " к " местного (ВАР K) и с помощью префикса-инкремент оператор (граф++), а не постфикс.

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;

Будет ли это быстрее или нет на данной среды является вопрос бенчмаркинга. Очень ограниченный выигрыш в производительности может быть в любом случае ожидается.

Комментарии (2)

Если вы действительно столкнулись с проблемой производительности, я бы предложил обернуть вызовы, добавляющие/удаляющие свойства объекта, функцией, которая также увеличивает/уменьшает соответствующим образом названное свойство (размер?).

Вам нужно только один раз вычислить начальное количество свойств и двигаться дальше. Если нет реальной проблемы с производительностью, не беспокойтесь. Просто оберните этот кусок кода в функцию getNumberOfProperties(object) и покончите с этим.

Комментарии (6)

Я не знаю, как это сделать, однако, чтобы свести количество итераций к минимуму, вы можете попробовать проверить существование __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__ функция будет срабатывать и пересчитывать.

Комментарии (4)

Как заявил Ави лен https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

будет делать трюк для всех перечислимых свойств объекта, но также включают в себя неперечислимый свойства можно использовать объект.getOwnPropertyNames`. Здесь's разница:

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

Как сказано здесь это имеет такое же поддержка браузеров как объект.ключи`

Однако, в большинстве случаев, вы не могли бы хотеть включать nonenumerables в подобных операциях, но это's всегда хорошо, чтобы знать разницу ;)

Комментарии (0)

Для прохода на avi объекта ответа льна.ключи(объект).длина является правильным для объекта, который не имеет функции привязаны к нему

пример:

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);});}} */

шаги, чтобы избежать этого:

  1. не ставьте функции в объект, который вы хотите посчитать количество ключей в

  2. использовать отдельный объект или сделать новый объект специально для функции (если вы хотите, чтобы подсчитать, сколько функций есть в файл, используя объект.ключи(объект).длина`)

и да я использовал _ или подчеркивания модуль с nodejs в моем примере

документацию можно найти здесь http://underscorejs.org/ а также ее исходный код на GitHub и различные другие данные

И, наконец, реализация лодашь https://lodash.com/docs#size

_.размер(в obj)

Комментарии (4)

как Ответил выше: `объект.ключи(объект).длина

Но: как у нас теперь есть карта класс в ЕС6, я бы предлагаю, чтобы использовать ее вместо использования свойства объекта.

const map = new Map();
map.set("key", "value");
map.size; // THE fastest way
Комментарии (0)

Для тех, кто Underscore.js включили в свой проект вы можете сделать:

_({a:'', b:''}).size() // => 2

или функционального стиля:

_.size({a:'', b:''}) // => 2
Комментарии (0)

От: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

объект.defineProperty(объект, реквизит, описатель)

Вы можете либо добавить его в всех ваших объектов:

Object.defineProperty(Object.prototype, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

Или один объект:

var myObj = {};
Object.defineProperty(myObj, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

Пример:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "leaked@example.com";
myObj.length; //output: 2

Добавила, что, кстати, он выиграл'т быть отображены в..в циклах:

for(var i in myObj) {
     console.log(i + ":" + myObj[i]);
}

Выход:

name:John Doe
email:leaked@example.com

Примечание: это не работает в < ИЕ9 браузерах.

Комментарии (0)

Как я'вэ решил эту проблему-построить свою собственную реализацию основной список, который ведет учет, сколько элементов хранится в объекте. Его очень простой. Что-то вроде этого:

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];
   }
}
Комментарии (9)

Вы можете использовать объект.ключи(данных).длина Найдите длину JSON-объект, имеющий ключевые данные

Комментарии (0)

Для тех, кто доб помощью JS 4 в свой проект вы можете сделать:

Ext.Object.getSize(myobj);

Преимуществом этого является то, что она'будете работать на всех совместимых браузерах доб (ИЕ6-ИЕ8 в комплекте), однако, я считаю, что время ничуть не лучше, чем o(n) времени, хотя, как и в других предложенных решений.

Комментарии (0)

ОП не'т указать, является ли объект узла, если это так, то вы можете просто использовать длина метод напрямую. Пример:

buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen'); 
Комментарии (0)

Если выше jQuery не работает, то попробуйте

$(Object.Item).length
Комментарии (1)

Вот некоторые тесты производительности для трех методов;

https://jsperf.com/get-the-number-of-keys-in-an-object

Объект##.ключи().длина

20,735 операций в секунду

Очень простой и совместимый. Работает быстро but дорого, потому что он создает новый массив ключей, который затем выбрасывается.

возвращаемый объект.ключи(objectToRead).длина;

петлю через ключи

15,734 операций в секунду

пусть размер=0; для(Пусть K в objectToRead) { размер++ } размер возврата;

Немного медленнее, но близко к памяти, так что, наверное, лучше, если вы'повторно заинтересованы в оптимизации для мобильного или других небольших машин

Используя карту вместо объекта

953,839,338 операций в секунду

возвращение mapToRead.размер;

В принципе, карта следы его собственного размера, так что мы'вновь возвращается в поле Номер. Гораздо быстрее, чем любой другой метод. Если у вас есть контроль над объектом, а не конвертировать их в карты.

Комментарии (0)

Вы можете использовать:

Object.keys(objectName).length; 

и

Object.values(objectName).length;
Комментарии (0)

Я стараюсь сделать его доступным для всех объект такой:

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
Комментарии (0)

Я не думаю, что это возможно (по крайней мере, без использования некоторых внутренних компонентов). И я не думаю, что вы много выиграете, оптимизируя это.

Комментарии (1)