Длина объекта JavaScript

2384

У меня есть объект JavaScript, есть ли встроенный или общепринятый способ получения длины этого объекта?

const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Гарет Симпсон
источник
15
Объектные литералы в javascript по умолчанию являются ассоциативными массивами, например, object.propertyName.propertyValue совпадает с object [propertyName] [propertyValue]
neitony
6
Добавлен однострочник в Underscore.js, который делает это: stackoverflow.com/a/11346637/11236
ripper234
31
После того, как ответ строки, используйте Object.keys (myArray) .length, как сказал @aeosynth.
Ранэдир Редди
67
хорошо, как насчетObject.keys(obj).length
Мухаммед Умер
5
Почему object.length не действителен? Это возвращает правильный результат для меня.
Адриан М

Ответы:

2624

Самый надежный ответ (то есть, который отражает намерение того, что вы пытаетесь сделать, вызывая при этом наименьшее количество ошибок):

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

// Get the size of an object
var size = Object.size(myObj);

В JavaScript есть своего рода соглашение, что вы не добавляете вещи в Object.prototype , потому что он может нарушать перечисления в различных библиотеках. Однако добавление методов в Object обычно безопасно.


Вот обновление от 2016 года и широкое развертывание ES5 и более поздних версий . Для IE9 + и всех других современных браузеров с поддержкой ES5 + вы можете использовать следующий Object.keys()код:

var size = Object.keys(myObj).length;

Это не должно изменять любой существующий прототип, так Object.keys()как теперь встроен.

Редактировать : Объекты могут иметь символические свойства, которые нельзя вернуть с помощью метода Object.key. Таким образом, ответ будет неполным без упоминания их.

Тип символа был добавлен в язык для создания уникальных идентификаторов свойств объекта. Основным преимуществом типа Symbol является предотвращение перезаписи.

Object.keysили Object.getOwnPropertyNamesне работает для символических свойств. Чтобы вернуть их вам нужно использовать Object.getOwnPropertySymbols.

var person = {
  [Symbol('name')]: 'John Doe',
  [Symbol('age')]: 33,
  "occupation": "Programmer"
};

const propOwn = Object.getOwnPropertyNames(person);
console.log(propOwn.length); // 1

let propSymb = Object.getOwnPropertySymbols(person);
console.log(propSymb.length); // 2

источник
65
@Tres - ваш код может быть поврежден, если кто-то придет и переопределит свойство 'size', не зная, что вы уже объявили его где-то в коде, поэтому всегда стоит проверять, определено ли оно уже
vsync
19
@vsync Вы очень правы. Нужно всегда проводить необходимые проверки вменяемости :)
Tres
132
Почему все игнорируют это:Object.keys(obj).length
Мухаммед Умер
33
@MuhammadUmer Возможно, потому что этот метод даже не существовал, когда этот ответ был написан. Даже сегодня его использование, вероятно, потребует полифилла для старых браузеров.
Крис Хейс
21
@stonyau IE8, IE9, IE10 - мертвые браузеры, которые не получают поддержки от Microsoft. Пользователи IE8, IE9, IE10 получают уведомление от Microsoft о том, что они используют старый неподдерживаемый браузер и должны ожидать, что они не будут работать для них. support.microsoft.com/en-us/kb/3123303
Лукас Лиезис
1709

Если вы знаете, что вам не нужно беспокоиться о hasOwnPropertyпроверках, вы можете сделать это очень просто:

Object.keys(myArray).length
aeosynth
источник
23
почему бы нет? от того, что я знаю, это стандарт: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
VSync
104
Это не универсально реализованный метод, но вы можете проверить, какой браузер поддерживает его с помощью этой таблицы .
Aeosynth
51
Нет поддержки IE8 = нет.
ripper234
22
время переключиться на firefox = к сожалению, вы не переключаетесь на пользователей вашего сайта ...
mdup
82
@ ripper234 нет поддержки IE = время для заполнения
Джон Дворжак
287

Обновлено : если вы используете Underscore.js (рекомендуется, он легкий!), То вы можете просто сделать

_.size({one : 1, two : 2, three : 3});
=> 3

Если нет , и вы не хотите возиться со свойствами объекта по какой-либо причине и уже используете jQuery, плагин одинаково доступен:

$.assocArraySize = function(obj) {
    // http://stackoverflow.com/a/6700/11236
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};
ripper234
источник
7
_.size()было идеальным решением для моего проекта Meteor , поддерживающего underscore.js.
tokyovariable
4
Я использую подчеркивание, и этот пост только напомнил мне, что я недостаточно использую его в этом проекте. Если вы обрабатываете объекты, у вас должен быть доступен underscore.js.
JBolanos
3
Подчеркнуть> (все - ['lo-dash'])
Rayjax
underscorejs, вещи, которые должны быть под js :)
minhajul
1
@Babydead, чтобы отличить реальные свойства объекта от наследственных. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
ripper234
56

Вот самое кросс-браузерное решение.

Это лучше, чем принятый ответ, потому что он использует нативный Object.keys, если существует. Таким образом, это самый быстрый для всех современных браузеров.

if (!Object.keys) {
    Object.keys = function (obj) {
        var arr = [],
            key;
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                arr.push(key);
            }
        }
        return arr;
    };
}

Object.keys(obj).length;
Joon
источник
6
Object.keys()возвращает массив, содержащий имена только тех свойств, которые являются перечисляемыми. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames()вместо этого. См developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
Джон Slegers
35

Я не эксперт по JavaScript, но похоже, что вам придется циклически проходить по элементам и считать их, поскольку у Object нет метода length:

var element_count = 0;
for (e in myArray) {  if (myArray.hasOwnProperty(e)) element_count++; }

@palmsey: справедливо для OP, документация JavaScript фактически явно ссылается на использование переменных типа Object таким образом, как «ассоциативные массивы».

jj33
источник
8
Не будет работать, потому что он будет также учитывать методы, добавленные через прототип.
Лайош Месарос
30

Этот метод получает все имена свойств вашего объекта в массиве, поэтому вы можете получить длину этого массива, равную длине ключей вашего объекта.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
venkat7668
источник
Метод ключей @PatrickRoberts не возвращает свойства из цепочки прототипов. Так почему необходимость в hasOwnProperty здесь. Также getOwnProperty будет возвращать скрытые свойства, так как длина указана в массиве и т. Д.
Мухаммед Умер
24

Чтобы не связываться с прототипом или другим кодом, вы можете создать и расширить свой собственный объект:

function Hash(){
    var length=0;
    this.add = function(key, val){
         if(this[key] == undefined)
         {
           length++;
         }
         this[key]=val;
    }; 
    this.length = function(){
        return length;
    };
}

myArray = new Hash();
myArray.add("lastname", "Simpson");
myArray.add("age", 21);
alert(myArray.length()); // will alert 2

Если вы всегда используете метод add, свойство length будет правильным. Если вы беспокоитесь о том, что вы или другие забыли об его использовании, вы можете добавить счетчик свойств, который другие опубликовали, также в методе length.

Конечно, вы всегда можете переписать методы. Но даже если вы это сделаете, ваш код, вероятно, заметно потерпит неудачу, упрощая отладку. ;)

DanMan
источник
Я думаю, что это лучшее решение, так как оно не требует зацикливания на 'for', которое может быть дорогостоящим, если массив большой
Emeka Mbah
20

Вот как и не забудьте проверить, что свойство не входит в цепочку прототипов:

var element_count = 0;
for(var e in myArray)
    if(myArray.hasOwnProperty(e))
        element_count++;
doekman
источник
20

Просто используйте это, чтобы получить length:

Object.keys(myObject).length
saurabhgoyal795
источник
7
объясните, пожалуйста, чем ваш ответ отличается от stackoverflow.com/a/6700/8632727
Патата,
3
Вы также не должны называть свой объектmyArray
Барри Майкл Дойл
2
@BarryMichaelDoyle я это изменил :)
saurabhgoyal795
Хорошо, всегда лучше называть переменные в соответствии с тем, что они есть на самом деле. Делает ваш код более читабельным для других разработчиков.
Барри Майкл Дойл
4
До редактирования "myArray" -> "myObject" это было идентично ответу с самым высоким рейтингом.
Yunnosch
16

Это совершенно другое решение, которое будет работать только в более современных браузерах (IE9 +, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+).

Смотрите jsFiddle

Настройте свой ассоциативный класс Array

/**
 * @constructor
 */
AssociativeArray = function () {};

// Make the length property work
Object.defineProperty(AssociativeArray.prototype, "length", {
    get: function () {
        var count = 0;
        for (var key in this) {
            if (this.hasOwnProperty(key))
                count++;
        }
        return count;
    }
});

Теперь вы можете использовать этот код следующим образом ...

var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);
союзник
источник
Я думаю, что это не безопасно. Например, он не может иметь элемент с ключом "length", оператор a1 ["length"] = "Hello world"; не может сохранить запись. Также оператор a1 ["hasOwnProperty"] = "некоторая опора"; тотально нарушает функцию
Panos Theof
3
@PanosTheof Я не думаю, что вы захотите, чтобы оно сохраняло значение, если вы использовали lengthсвойство, любой код, который использовал его, должен был бы гарантировать, что оно не будет пытаться сохранить его length, но я думаю, что это было бы то же самое, если бы оно было стандартный массив тоже. Переопределение hasOwnPropertyлюбого объекта, скорее всего, приведет к нежелательному результату.
Союзник
16

<script>
myObj = {"key1" : "Hello", "key2" : "Goodbye"};
var size = Object.keys(myObj).length;
console.log(size);
</script>

<p id="myObj">The number of <b>keys</b> in <b>myObj</b> are: <script>document.write(size)</script></p>

Это работает для меня:

var size = Object.keys(myObj).length;
Giovanni G. PY
источник
15

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

Янис Элмерис
источник
15

Использование:

var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)

Махендра Кулькарни
источник
14

@palmsey: по справедливости для OP, документы javascript на самом деле явно ссылаются на использование переменных типа Object таким образом, как «ассоциативные массивы».

И, честно говоря, @palmsey он был совершенно прав: они не ассоциативные массивы, а определенно объекты :) - выполняющие работу ассоциативного массива. Но что касается более широкой темы, вы определенно имеете на это право в соответствии с этой довольно хорошей статьей, которую я нашел:

JavaScript «Ассоциативные массивы» считается вредным

Но в соответствии с этим, не является ли принятый ответ самой плохой практикой?

Укажите функцию прототипа size () для объекта

Если что-то еще было добавлено в Object .prototype, то предложенный код завершится ошибкой:

<script type="text/javascript">
Object.prototype.size = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
Object.prototype.size2 = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>

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

Polsonby
источник
13

Если вам нужна ассоциативная структура данных, которая показывает ее размер, лучше использовать карту вместо объекта.

const myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
Ориоль
источник
11

Как насчет чего-то вроде этого -

function keyValuePairs() {
    this.length = 0;
    function add(key, value) { this[key] = value; this.length++; }
    function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}
Джерри
источник
11

Если у нас есть хэш

hash = {"a": "b", "c": "d"};

мы можем получить длину, используя длину ключей, которая является длиной хеша:

ключи (хэш) .length

Або-elleef
источник
2
Это отличный ответ, однако я не могу найти документацию для этой функции клавиш. Так что я не могу быть уверен в поддержке кросс-браузера.
Чим
1
К сожалению, это не такой хороший ответ, как я сначала подумал! Оказывается, функция клавиш доступна только в веб-консолях Chrome и Firefox. Если вы вставите этот код в сценарий, то произойдет сбой при Uncaught ReferenceError: ключи не определены
chim
1
Чем это отличается от ответа aeosynth ?
Питер Мортенсен
11
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
  1. Object.values ​​(MyObject) .length
  2. Object.entries (MyObject) .length
  3. Object.keys (MyObject) .length
tdjprog
источник
Какой из них быстрее среди вышеперечисленных 3.
siluveru kiran kumar
Object.values ​​(myObject) .length
tdjprog
как мы можем сказать, что Object.values ​​(myObject) .length быстрее, есть ли пример? Спасибо, @tdjprog
siluveru Киран Кумар
просто попробуйте это в консоли:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog
почему Object.values ​​(myObject) .length быстрее, где Object.entries (myObject) .length не выдает результат даже через некоторое время, в чем причина? Спасибо @tdjprog
Siluveru Киран Кумар
10

Если вы используете AngularJS 1.x, вы можете делать вещи AngularJS путем создания фильтра и использования кода из любого другого примера, такого как:

// Count the elements in an object
app.filter('lengthOfObject', function() {
  return function( obj ) {
    var size = 0, key;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) size++;
    }
   return size;
 }
})

Применение

В вашем контроллере:

$scope.filterResult = $filter('lengthOfObject')($scope.object)

Или по вашему мнению:

<any ng-expression="object | lengthOfObject"></any>
pcnate
источник
4
ОП не запросил версию AngularJS. Это неверный ответ на вопрос.
Франциско Ходж
10

Самый простой способ такой

Object.keys(myobject).length

где myobject - это объект того, что вы хотите, чтобы длина

Mithu A Quayium
источник
2
Похоже, это просто повторение существующего ответа .
Пан
@Pang согласился, и он не дает никакого дополнительного контекста, как другие ответы.
Мистическое
8

Если вам не нужна поддержка Internet Explorer 8 или ниже, вы можете легко получить количество свойств в объекте, выполнив следующие два шага:

  1. Запустите либо Object.keys()для получения массива, содержащего имена только тех свойств, которые являются перечисляемыми, либо, Object.getOwnPropertyNames()если вы хотите также включить имена свойств, которые не перечислимы.
  2. Получить .lengthсвойство этого массива.

Если вам нужно сделать это более одного раза, вы можете заключить эту логику в функцию:

function size(obj, enumerablesOnly) {
    return enumerablesOnly === false ?
        Object.getOwnPropertyNames(obj).length :
        Object.keys(obj).length;
}

Как использовать эту функцию:

var myObj = Object.create({}, {
    getFoo: {},
    setFoo: {}
});
myObj.Foo = 12;

var myArr = [1,2,5,4,8,15];

console.log(size(myObj));        // Output : 1
console.log(size(myObj, true));  // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr));        // Output : 6
console.log(size(myArr, true));  // Output : 6
console.log(size(myArr, false)); // Output : 7

Смотрите также эту скрипку для демонстрации.

Джон Слегерс
источник
8

Используйте, Object.keys(myObject).lengthчтобы получить длину объекта / массива

var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

console.log(Object.keys(myObject).length); //3
shaheb
источник
8
const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

console.log(Object.keys(myObject).length)

// o/p 3
Dev216
источник
7

Вариация некоторых из вышеперечисленных:

var objLength = function(obj){    
    var key,len=0;
    for(key in obj){
        len += Number( obj.hasOwnProperty(key) );
    }
    return len;
};

Это немного более элегантный способ интеграции hasOwnProp.

Уэйд Харрелл
источник
6

Вот другая версия ответа Джеймса Когана. Вместо передачи аргумента просто создайте прототип класса Object и сделайте код чище.

Object.prototype.size = function () {
    var size = 0,
        key;
    for (key in this) {
        if (this.hasOwnProperty(key)) size++;
    }
    return size;
};

var x = {
    one: 1,
    two: 2,
    three: 3
};

x.size() === 3;

Пример jsfiddle: http://jsfiddle.net/qar4j/1/

Шерзод
источник
6
Object.prototype- плохая идея.
Дзяд Боровы,
@tborychowski Не могли бы вы объяснить, почему?
Мохамад
вот одна статья: bit.ly/1droWrG . Я не говорю, что это не должно быть сделано, только то, что вам нужно знать все последствия, прежде чем вы это сделаете.
Дзяд Боровы
Если вы собираетесь расширить встроенные прототипы или заполнить свойство (например, monkey-patch), пожалуйста, сделайте это правильно: для прямой совместимости сначала проверьте, существует ли свойство, а затем сделайте свойство не перечисляемым, чтобы собственные ключи из построенных объектов не загрязнены. Для методов используйте актуальные методы . Моя рекомендация: следуйте этим примерам, которые демонстрируют, как добавить метод, который ведет себя как можно более близко, как встроенные методы.
user4642212
5

Вы можете просто использовать Object.keys(obj).lengthлюбой объект, чтобы получить его длину. Object.keys возвращает массив, содержащий все ключи объекта (свойства), которые могут пригодиться для определения длины этого объекта по длине соответствующего массива. Вы даже можете написать функцию для этого. Давайте проявим творческий подход и напишем для него метод (вместе с более удобным свойством getter):

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

console.log(objLength({a:1, b:"summit", c:"nonsense"}));

// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));

// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
   return Object.keys(this).length;
}
console.log(obj.getLength());

// You can also write it as a method, which is more efficient as done so above

Object.defineProperty(Object.prototype, "length", {get:function(){
    return Object.keys(this).length;
}});
console.log(obj.length);

// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()

мистический
источник
3
Чем это отличается от ответа aeosynth ?
Питер Мортенсен
Это потому, что он показывает, как сделать его как функцию и метод глобального объекта (более объектно-ориентированный и использует некоторую форму инкапсуляции); Однако ответ Aeosynth не.
Мистический
Если вы собираетесь расширить встроенные прототипы или заполнить свойство (например, monkey-patch), пожалуйста, сделайте это правильно: для прямой совместимости сначала проверьте, существует ли свойство, а затем сделайте свойство не перечисляемым, чтобы собственные ключи из построенных объектов не загрязнены. Для методов используйте актуальные методы . Моя рекомендация: следуйте этим примерам, которые демонстрируют, как добавить метод, который ведет себя как можно более близко, как встроенные методы.
user4642212
Кроме того, как написание метода «более эффективным»?
user4642212
5

Вы всегда можете сделать так, Object.getOwnPropertyNames(myObject).lengthчтобы получить тот же результат, [].lengthчто и для обычного массива.

Pian0_M4n
источник
1
Object.keys()возвращает массив, содержащий имена только тех свойств, которые являются перечисляемыми. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames()вместо этого. См developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
Джон Slegers
3
Чем это отличается от ответа aeosynth ?
Питер Мортенсен
4

Мы можем найти длину объекта с помощью:

Object.values(myObject).length
Solanki ...
источник
4

Немного опоздал к игре, но хороший способ добиться этого (только для IE9 +) - определить магический метод получения свойства length:

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

И вы можете просто использовать его так:

var myObj = { 'key': 'value' };
myObj.length;

Дал бы 1.

MacRoman
источник
1
За исключением аргументов против модификации прототипа, лично у меня НИКОГДА не было ошибки, вызванной этим, и для меня это одна из сильных сторон JavaScript.
MacroMan
3

Ниже приведена версия ответа Джеймса Коглана в CoffeeScript для тех, кто отказался от прямого JavaScript :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size
Эрик Андерсон
источник
1
Вы, вероятно, хотели сказать size++ for own key of obj( own keyсинтаксис сахара в CoffeeScript). Использование hasOwnPropertyнепосредственно из объекта опасно, поскольку оно нарушается, когда объект действительно обладает таким свойством.
Конрад Боровски,
2
ОП не запрашивал версию CoffeeScript и не помечался как таковой. Это неверный ответ на вопрос.
Франциско Ходж