Какой самый быстрый способ подсчитать количество ключей/свойств объекта? Можно ли это сделать без итерации над объектом? Т.е. не делая
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox предоставлял волшебное свойство __count__
, но оно было удалено где-то в четвертой версии).
Для этого в любом в ES5-совместимая среда, например, узел, хром, IE 9+ и выше, Firefox 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;
Если вы используете Underscore.js вы можете использовать _.размер (спасибо @его Douwe):
_.размер(в obj)
В качестве альтернативы вы можете также использовать _.ключи что может быть понятнее для некоторых: `_.ключи(объект).длина
Я настоятельно рекомендую подчеркнуть, ее плотный библиотеки делают много элементарных вещей. По возможности они соответствовали ECMA5 и прислушивайтесь к собственной реализации.
В противном случае я поддерживаю @Ави'ы ответ. Я редактировал его, чтобы добавить ссылку в ЛДЦ док, который включает в себя ключи() способ вы можете добавить не ECMA5 браузерах.
Стандартная реализация объекта (в ES5.1 объект внутренних свойств и методов) не требует объект
, чтобы отслеживать его количество ключей/свойства, поэтому не должно быть никакого стандартного способа определить размер "объекта" без явно или неявно перебора ключей.
Итак, вот наиболее часто используемые варианты:
в
Объект.ключи(объект).длина;
работ внутренне перебирать ключи, чтобы вычислить временный массив и возвращает его длину.
Многие библиотеки на основе примеров других в этом разделе находятся полезные идиомы в контексте их библиотека. С точки зрения производительности, однако, нет ничего, чтобы получить, по сравнению с идеальным нет-код библиотеки, так как все эти методы на самом деле инкапсулировать либо цикл for или объекта в ES5.ключи
(родной или обертке).
В медленная часть такого цикла вообще .метод 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;
Будет ли это быстрее или нет на данной среды является вопрос бенчмаркинга. Очень ограниченный выигрыш в производительности может быть в любом случае ожидается.
Если вы действительно столкнулись с проблемой производительности, я бы предложил обернуть вызовы, добавляющие/удаляющие свойства объекта, функцией, которая также увеличивает/уменьшает соответствующим образом названное свойство (размер?).
Вам нужно только один раз вычислить начальное количество свойств и двигаться дальше. Если нет реальной проблемы с производительностью, не беспокойтесь. Просто оберните этот кусок кода в функцию 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
будет делать трюк для всех перечислимых свойств объекта, но также включают в себя неперечислимый свойства можно использовать объект.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 всегда хорошо, чтобы знать разницу ;)
Для прохода на 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);});}} */
шаги, чтобы избежать этого:
не ставьте функции в объект, который вы хотите посчитать количество ключей в
использовать отдельный объект или сделать новый объект специально для функции (если вы хотите, чтобы подсчитать, сколько функций есть в файл, используя объект.ключи(объект).длина`)
и да я использовал _ или подчеркивания модуль с nodejs в моем примере
документацию можно найти здесь http://underscorejs.org/ а также ее исходный код на GitHub и различные другие данные
И, наконец, реализация лодашь https://lodash.com/docs#size
_.размер(в obj)
От: 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 = "[email protected]";
myObj.length; //output: 2
Добавила, что, кстати, он выиграл'т быть отображены в..в циклах:
for(var i in myObj) {
console.log(i + ":" + myObj[i]);
}
Выход:
name:John Doe
email:[email protected]
Примечание: это не работает в < ИЕ9 браузерах.
Как я'вэ решил эту проблему-построить свою собственную реализацию основной список, который ведет учет, сколько элементов хранится в объекте. Его очень простой. Что-то вроде этого:
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];
}
}
Для тех, кто доб помощью JS 4 в свой проект вы можете сделать:
Ext.Object.getSize(myobj);
Преимуществом этого является то, что она'будете работать на всех совместимых браузерах доб (ИЕ6-ИЕ8 в комплекте), однако, я считаю, что время ничуть не лучше, чем o(n) времени, хотя, как и в других предложенных решений.
ОП не'т указать, является ли объект узла, если это так, то вы можете просто использовать длина метод напрямую. Пример:
buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen');
Если выше jQuery не работает, то попробуйте
$(Object.Item).length
Вот некоторые тесты производительности для трех методов;
https://jsperf.com/get-the-number-of-keys-in-an-object
Объект##.ключи().длина
20,735 операций в секунду
Очень простой и совместимый. Работает быстро but дорого, потому что он создает новый массив ключей, который затем выбрасывается.
возвращаемый объект.ключи(objectToRead).длина;
15,734 операций в секунду
пусть размер=0; для(Пусть K в objectToRead) { размер++ } размер возврата;
Немного медленнее, но близко к памяти, так что, наверное, лучше, если вы'повторно заинтересованы в оптимизации для мобильного или других небольших машин
953,839,338 операций в секунду
возвращение mapToRead.размер;
В принципе, карта следы его собственного размера, так что мы'вновь возвращается в поле Номер. Гораздо быстрее, чем любой другой метод. Если у вас есть контроль над объектом, а не конвертировать их в карты.
Вы можете использовать:
Object.keys(objectName).length;
и
Object.values(objectName).length;
Я стараюсь сделать его доступным для всех объект такой:
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