Количество элементов в объекте javascript

104

Есть ли способ получить (откуда-то) количество элементов в объекте javascript ?? (т.е. постоянная временная сложность).

Я не могу найти свойство или метод, позволяющий получить эту информацию. Пока что я могу думать только об итерации по всей коллекции, но это линейное время.
Странно, что нет прямого доступа к размеру объекта, не правда ли?

РЕДАКТИРОВАТЬ:
я говорю об Objectобъекте (а не об объектах в целом):

var obj = new Object ;
Получить бесплатно
источник
5
Уже ответили здесь stackoverflow.com/questions/126100/... Object.keys (OBJ) .length
размолвки

Ответы:

155

Хотя реализации JS могут отслеживать такое значение внутренне, стандартного способа получить его не существует.

Раньше вариант Mozilla Javascript обнаруживал нестандартность__count__ , но в версии 1.8.5 он был удален.

Для кроссбраузерного сценария вы застряли в явном переборе свойств и проверке hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

В случае реализаций с поддержкой ECMAScript 5 это также можно записать как (Престижность Avi Flax )

function countProperties(obj) {
    return Object.keys(obj).length;
}

Имейте в виду, что вы также пропустите свойства, которые нельзя перечислить (например, массив length).

Если вы используете такие фреймворки, как jQuery, Prototype, Mootools, $ what-the-newest-hype, проверьте, поставляются ли они с собственным API коллекций, что может быть лучшим решением вашей проблемы, чем использование собственных объектов JS.

Кристоф
источник
11
Черт возьми, я всегда забываю hasOwnProperty. Слишком много времени на земле .NET, говорю вам. +1
annakata 05
2
jQuery использует объект для своих коллекций, который он получает из запросов, и предоставляет это значение с помощью свойства length.
Nosredna 05
6
Firefox4 __count__ушел :(
Timo Huovinen
1
Есть ли способ сделать это без for in? Я использую тот же тип привязки, но я бы хотел, чтобы он передавал JSLint, если это вообще возможно.
уличный фонарь
1
зачем нам это нужно hasOwnProperty()?
swisswiss
100

Для этого в любой ES5-совместимой среде

Object.keys(obj).length

(Поддержка браузера отсюда )
(Документ по Object.keys здесь , включает метод, который вы можете добавить в браузеры, отличные от ECMA5)

ZelkiN
источник
2
Это не тот вопрос, на который можно дать такой ответ. При этом вы берете все ключи объекта, помещаете их во вновь созданный массив, а затем извлекаете свойство length из этого нового массива.
GetFree
13
Возможно, он не самый эффективный с точки зрения программирования, но он наиболее эффективен для разработчиков.
superluminary
9

если вы уже используете jQuery в своей сборке, просто сделайте следующее:

$(yourObject).length

У меня это хорошо работает с объектами, и у меня уже был jQuery в качестве зависимости.

Несмываемый
источник
5
Странно ... у меня это не работает. Я всегда получаю 1. Ответ ZelkiN у меня работает.
Майк грызун
3
Этот код всегда возвращает 1. Всего 1 объект. Это не считая элементов в нем
BeRocket
5
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);
Kennebec
источник
2

AFAIK, нет возможности сделать это надежно, если вы не переключитесь на массив. Что, честно говоря, не кажется странным - мне кажется довольно очевидным, что массивы являются счетными, а объекты - нет.

Вероятно, самое близкое, что вы получите, это что-то вроде этого

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

Но это создает проблемы или, по крайней мере, вопросы. Подсчитываются все созданные пользователем свойства, включая саму функцию _length! И хотя в этом простом примере вы можете избежать этого, просто используя обычную функцию, это не значит, что вы можете запретить другим скриптам делать это. так что ты делаешь? Игнорировать свойства функции?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

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

Питер Бейли
источник
8
ОПАСНО БУДЕТ РОБИНСОН! У НЕ прото против объекта! Все происходит от Object, вы нарушите обработку клиента таким образом, если выполняете какой-либо значительный объем работы JS.
annakata 05
5
Эээ ... разве вы не читали ту часть, где я написал в комментарии «Обезьяна исправляет намеренно, чтобы подчеркнуть точку зрения» - да ладно, я сделал это специально, чтобы люди не волновались об этом. Кроме того, хотя я не сторонник обезьяньего патча, вы неправильно понимаете, как работает цепочка прототипов в Javascript, если думаете, что это вызовет проблемы с производительностью video.yahoo.com/watch/111585/1027823
Питер Бейли
Итак .. это делать или не делать?
OscarRyz 02
В «Javascript: The Good Parts» он создает прототип объекта с помощью метода create (). Я полагаю, что это окончательная книга по Javascript.
Крис Датроу
1

Концепция числа / длины / размерности на самом деле не имеет смысла для объекта, и необходимость в этом говорит о том, что вы действительно хотите для меня массив.

Изменить: указал мне, что вам нужен O (1) для этого. Боюсь, что, насколько мне известно, такого способа не существует.

аннаката
источник
Он предложил повторить сам, каково это решение. Ему нужен был О (1) способ достичь этого ...
Томас Хансен
Вы совершенно правы. Действительно стоит более внимательно читать вопросы.
annakata 05
Собственно, объекты - это самое близкое к Map, что есть в JS. Карты действительно имеют длину.
Cristian Vrabie