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

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

const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
7.08.2008 19:42:21
Объектные литералы в javascript по умолчанию являются ассоциативными массивами, например, object.propertyName.propertyValue совпадает с object [propertyName] [propertyValue]
neitony 13.02.2011 16:19:06
Добавлен однострочник в Underscore.js, который делает это: stackoverflow.com/a/11346637/11236
ripper234 8.07.2012 10:31:15
После ответа на строку используйте Object.keys (myArray) .length, как сказал @aeosynth.
Ranadheer Reddy 22.06.2013 07:50:58
хорошо, как насчетObject.keys(obj).length
Muhammad Umer 25.02.2015 00:14:31
Почему object.length не действителен? Это возвращает правильный результат для меня.
Adrian M 26.06.2016 17:01:08
30 ОТВЕТОВ
РЕШЕНИЕ

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

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
2580
19.05.2019 14:49:29
@Tres - ваш код может быть поврежден, если кто-то придет и переопределит свойство 'size', не зная, что вы уже объявили его где-то в коде, поэтому всегда стоит проверять, определено ли оно уже
vsync 14.06.2011 11:30:19
@vsync Вы очень правы. Нужно всегда проводить необходимые проверки вменяемости :)
Tres 24.06.2011 02:03:57
Почему все игнорируют это:Object.keys(obj).length
Muhammad Umer 25.02.2015 00:14:15
@MuhammadUmer Возможно, потому что этот метод даже не существовал, когда этот ответ был написан. Даже сегодня его использование, вероятно, потребует полифилла для старых браузеров.
Chris Hayes 9.05.2015 01:53:56
@stonyau IE8, IE9, IE10 - мертвые браузеры, которые не получают поддержки от Microsoft. Пользователи IE8, IE9, IE10 получают уведомление от Microsoft о том, что они используют старый неподдерживаемый браузер и должны ожидать, что они не будут работать для них. support.microsoft.com/en-us/kb/3123303
Lukas Liesis 19.01.2016 09:08:39

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

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

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

35
17.09.2016 18:27:26
Не будет работать, потому что он будет также учитывать методы, добавленные через прототип.
Lajos Meszaros 8.10.2013 11:32:57

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

var element_count = 0;
for(var e in myArray)
    if(myArray.hasOwnProperty(e))
        element_count++;
20
23.05.2012 23:28:42

@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 и проверять тип членов при их итерации.

14
23.05.2017 12:34:58

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

Object.keys(myArray).length
1687
21.06.2017 20:12:12
почему бы и нет? от того, что я знаю, это стандарт: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
vsync 6.06.2011 11:51:43
Это не универсально реализованный метод, но вы можете проверить, какой браузер поддерживает его с помощью этой таблицы .
aeosynth 6.06.2011 19:08:53
Нет поддержки IE8 = нет.
ripper234 31.01.2012 10:16:29
время переключиться на firefox = к сожалению, вы не переключаетесь на пользователей вашего сайта ...
mdup 13.08.2012 11:25:15
@ ripper234 нет поддержки IE = время для заполнения
John Dvorak 13.12.2012 06:27:43

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

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.

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

24
8.08.2015 01:37:04
Я думаю, что это лучшее решение, так как оно не требует зацикливания на 'for', которое может быть дорогостоящим, если массив большой
Emeka Mbah 1.06.2016 19:53:54

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

15
29.07.2011 13:41:54

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

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
24.08.2011 14:26:28

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

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

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

7
7.10.2014 10:54:43

Обновлено : если вы используете 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;
};
281
8.07.2012 10:30:58
_.size()было идеальным решением для моего проекта Meteor , поддерживающего underscore.js.
tokyovariable 1.08.2013 17:05:55
Я использую подчеркивание, и этот пост только напомнил мне, что я недостаточно использую его в этом проекте. Если вы обрабатываете объекты, у вас должен быть доступен underscore.js.
jbolanos 20.11.2013 20:51:38
Подчеркнуть> (все - ['lo-dash'])
Rayjax 11.04.2014 08:13:20
underscorejs, вещи, которые должны быть под js :)
minhajul 30.10.2015 10:02:47
@Babydead, чтобы отличить реальные свойства объекта от наследственных. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
ripper234 12.02.2017 19:56:20

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

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size
3
6.10.2014 19:44:08
Вы, вероятно, хотели сказать size++ for own key of obj( own keyсинтаксис сахара в CoffeeScript). Использование hasOwnPropertyнепосредственно из объекта опасно, поскольку оно нарушается, когда объект действительно обладает таким свойством.
Konrad Borowski 1.09.2013 10:47:11
ОП не запрашивал версию CoffeeScript и не помечался как таковой. Это неверный ответ на вопрос.
Francisco Hodge 4.12.2015 21:01:49

Вот другая версия ответа Джеймса Когана. Вместо передачи аргумента просто создайте прототип класса 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
26.06.2013 23:47:45
Object.prototype- плохая идея.
Dziad Borowy 14.10.2013 10:50:14
@tborychowski Не могли бы вы объяснить, почему?
Mohamad 5.03.2014 13:09:41
вот одна статья: bit.ly/1droWrG . Я не говорю, что это не должно быть сделано, только то, что вам нужно знать все последствия, прежде чем вы это сделаете.
Dziad Borowy 5.03.2014 15:55:08

Это совершенно другое решение, которое будет работать только в более современных браузерах (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);
16
2.08.2013 09:01:07
Я думаю, что это не безопасно. Например, он не может иметь элемент с ключом "length", оператор a1 ["length"] = "Hello world"; не может сохранить запись. Также оператор a1 ["hasOwnProperty"] = "некоторая опора"; тотально нарушает функцию
Panos Theof 26.10.2014 11:16:54
@PanosTheof Я не думаю, что вы захотите, чтобы оно сохраняло значение, если вы использовали lengthсвойство, любой код, который использовал его, должен был бы гарантировать, что оно не будет пытаться сохранить его length, но я думаю, что если бы оно было стандартный массив тоже. Переопределение hasOwnPropertyлюбого объекта, скорее всего, приведет к нежелательному результату.
Ally 27.10.2014 00:03:39

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

Это лучше, чем принятый ответ, потому что он использует нативный 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;
56
1.09.2013 16:12:06
Object.keys()возвращает массив, содержащий имена только тех свойств, которые перечисляются. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames()вместо этого. См developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
John Slegers 7.03.2016 12:40:48

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

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

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

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

11
17.09.2016 18:28:53
Это отличный ответ, однако я не могу найти документацию для этой функции клавиш. Так что я не могу быть уверен в поддержке кросс-браузера.
chim 3.09.2015 09:54:56
К сожалению, это не такой хороший ответ, как я сначала подумал! Оказывается, функция клавиш доступна только в веб-консолях Chrome и Firefox. Если вы вставите этот код в сценарий, то произойдет сбой при Uncaught ReferenceError: ключи не определены
chim 3.09.2015 10:14:33
Чем это отличается от ответа aeosynth ?
Peter Mortensen 17.09.2016 18:32:40

Как и большинство проблем JavaScript, есть много решений. Вы можете расширить объект, который, к лучшему или худшему, работает как словарь многих других языков (+ граждане первого класса). В этом нет ничего плохого, но другой вариант - создать новый объект, который соответствует вашим конкретным потребностям.

function uberject(obj){
    this._count = 0;
    for(var param in obj){
        this[param] = obj[param];
        this._count++;
    }
}

uberject.prototype.getLength = function(){
    return this._count;
};

var foo = new uberject({bar:123,baz:456});
alert(foo.getLength());
2
19.11.2016 06:27:26
не модифицируйте прототип :)
zero_cool 1.10.2018 22:45:53
Модификация прототипа фабричной функции - это способ их расширения.
Ron Sims II 3.10.2018 15:35:02

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

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
30
6.02.2015 19:43:01
Метод ключей @PatrickRoberts не возвращает свойства из цепочки прототипов. Так почему необходимость в hasOwnProperty здесь. Также getOwnProperty будет возвращать скрытые свойства, так как длина указана в массиве и т. Д.
Muhammad Umer 26.02.2015 16:07:25

Свойство

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

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

var o = {a: 1, b: 2, c: 3};
alert(o.length); // <-- 3
o['foo'] = 123;
alert(o.length); // <-- 4
3
6.01.2015 19:10:35

Простое решение:

  var myObject = {};      // ... your object goes here.

  var length = 0;

  for (var property in myObject) {
    if (myObject.hasOwnProperty(property)){
      length += 1;
    }
  };

  console.log(length);    // logs 0 in my example.
1
11.04.2015 14:33:17

Если вы используете 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>
10
17.09.2016 18:33:46
ОП не запросил версию AngularJS. Это неверный ответ на вопрос.
Francisco Hodge 4.12.2015 21:07:07

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

5
27.09.2017 09:05:26
Object.keys()возвращает массив, содержащий имена только тех свойств, которые перечисляются. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames()вместо этого. См developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
John Slegers 7.03.2016 12:39:44
Чем это отличается от ответа aeosynth ?
Peter Mortensen 17.09.2016 18:35:14

Если вам не нужна поддержка 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
18.09.2016 00:19:08

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

const myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
12
24.11.2019 01:55:01

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

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

15
17.09.2016 18:36:54

Решение работает для многих случаев и кросс-браузер:

Код

var getTotal = function(collection) {

    var length = collection['length'];
    var isArrayObject =  typeof length == 'number' && length >= 0 && length <= Math.pow(2,53) - 1; // Number.MAX_SAFE_INTEGER

    if(isArrayObject) {
        return collection['length'];
    }

    i= 0;
    for(var key in collection) {
        if (collection.hasOwnProperty(key)) {
            i++;
        }
    }

    return i;
};

Примеры данных:

// case 1
var a = new Object();
a["firstname"] = "Gareth";
a["lastname"] = "Simpson";
a["age"] = 21;

//case 2
var b = [1,2,3];

// case 3
var c = {};
c[0] = 1;
c.two = 2;

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

getLength(a); // 3
getLength(b); // 3
getLength(c); // 2
0
7.08.2016 16:28:48

Вы можете просто использовать 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()

5
12.10.2016 02:09:14
Чем это отличается от ответа aeosynth ?
Peter Mortensen 17.09.2016 18:39:02
Это потому, что он показывает, как сделать его как функцию и метод глобального объекта (более объектно-ориентированный и использует некоторую форму инкапсуляции); Однако ответ Aeosynth не.
Mystical 18.09.2016 01:34:25

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

Object.values(myObject).length
4
22.05.2017 13:42:23

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

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

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

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

Дал бы 1.

4
4.07.2017 15:27:19
За исключением аргументов против модификации прототипа, лично у меня НИКОГДА не было ошибки, вызванной этим, и для меня это одна из сильных сторон JavaScript.
MacroMan 13.08.2019 09:31:35

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

Object.keys(myObject).length
19
4.04.2018 08:27:18
объясните, пожалуйста, чем ваш ответ отличается от stackoverflow.com/a/6700/8632727
Patata 13.02.2018 13:04:28
Вы также не должны называть свой объектmyArray
Barry Michael Doyle 21.03.2018 09:48:59
@BarryMichaelDoyle я изменил это :)
saurabhgoyal795 29.03.2018 10:10:57
Хорошо, всегда лучше называть переменные в соответствии с тем, что они есть на самом деле. Делает ваш код более читабельным для других разработчиков.
Barry Michael Doyle 4.04.2018 08:26:47
До редактирования "myArray" -> "myObject" это было идентично ответу с самым высоким рейтингом.
Yunnosch 25.05.2018 06:44:27
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
10
5.04.2018 23:45:02
Какой из них быстрее среди вышеперечисленных 3.
siluveru kiran kumar 21.06.2019 07:23:22
Object.values ​​(myObject) .length
tdjprog 1.07.2019 21:11:37
Как мы можем сказать, что Object.values ​​(myObject) .length быстрее, есть ли пример? Спасибо, @tdjprog
siluveru kiran kumar 2.07.2019 07:02:20
просто попробуйте это в консоли:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog 3.07.2019 01:25:05
почему Object.values ​​(myObject) .length быстрее, где Object.entries (myObject) .length не выдает результат даже через некоторое время, в чем причина? Спасибо @tdjprog
siluveru kiran kumar 3.07.2019 07:02:17