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

2039

Если у меня есть объект JavaScript, скажите

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

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

  • 12
    Объектные литералы в javascript по умолчанию являются ассоциативными массивами, например, object.propertyName.propertyValue совпадает с object [propertyName] [propertyValue]
  • 6
    Добавлен однострочный файл в Underscore.js, который делает это: stackoverflow.com/a/11346637/11236
Показать ещё 8 комментариев
Теги:
javascript-objects

38 ответов

2256
Лучший ответ

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

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(myArray);

В 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
  • 60
    @Tres - ваш код может быть поврежден, если кто-то придет и переопределит свойство 'size', не зная, что вы уже объявили его где-то в коде, поэтому всегда стоит проверять, уже определено ли оно
  • 16
    @vsync Вы очень правы. Нужно всегда проводить необходимые проверки здравомыслия :)
Показать ещё 12 комментариев
1478

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

Object.keys(myArray).length
  • 23
    почему бы и нет? насколько я знаю, это стандарт: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
  • 101
    Это не универсально реализованный метод, но вы можете проверить, какой браузер поддерживает его с помощью этой таблицы .
Показать ещё 18 комментариев
258

Обновлено. Если вы используете 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;
};
  • 7
    _.size() было идеальным решением для моего проекта Meteor , который имеет поддержку underscore.js.
  • 4
    Я использую подчеркивание, и этот пост только напомнил мне, что я недостаточно использую его в этом проекте. Если вы обрабатываете объекты, у вас должен быть доступен underscore.js.
Показать ещё 5 комментариев
139

Используйте что-то простое:

Object.keys(obj).length

Это не должно быть сложно и определенно не требует выполнения другой функции.

43

Здесь самое перекрестное браузерное решение.

Это лучше, чем принятый ответ, потому что он использует собственные 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;
  • 4
    Object.keys() возвращает массив, содержащий имена только тех свойств, которые можно перечислить. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames() . См. Developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
30

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

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

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

  • 6
    Не будет работать, потому что он также будет учитывать методы, добавленные через прототип.
24

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

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

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

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 будет правильным. Если вы беспокоитесь о том, что вы или другие люди забыли о его использовании, вы можете добавить счетчик свойств, который другие отправили также методу длины.

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

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

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

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

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

См. jsFiddle

Установите класс ассоциативной матрицы

/**
 * @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);
  • 0
    Я думаю, что это не безопасно. Например, он не может иметь элемент с ключом "length", оператор a1 ["length"] = "Hello world"; не может сохранить запись. Также оператор a1 ["hasOwnProperty"] = "некоторая опора"; тотально нарушает функцию
  • 3
    @PanosTheof Я не думаю, что вы захотите, чтобы оно сохраняло значение, если вы использовали свойство length , любой код, который использовал его, должен был бы гарантировать, что оно не будет пытаться сохранить против length , но я думаю, что это будет то же самое, если это был стандартный массив тоже. Переопределение hasOwnProperty для любого объекта, скорее всего, приведет к нежелательному результату.
13

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

12

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

Object.keys(myObject).length
12

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

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

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

Object.keys(myObject).length
  • 5
    объясните, пожалуйста, чем ваш ответ отличается от stackoverflow.com/a/6700/8632727
  • 2
    Вы также не должны называть свой объект myArray
Показать ещё 3 комментария
11

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

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

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

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

Укажите функцию prototype size() для Object

Если что-то еще добавлено в 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>

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

9

Если вы используете 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>
  • 4
    ОП не запросил версию AngularJS. Это неверный ответ на вопрос.
9

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

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

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

клавиши (хэш).length

  • 1
    Это отличный ответ, однако я не могу найти документацию для этой функции клавиш. Так что я не могу быть уверен в поддержке кросс-браузера.
  • 1
    К сожалению, это не такой хороший ответ, как я сначала подумал! Оказывается, функция клавиш доступна только в веб-консолях Chrome и Firefox. Если вы вставите этот код в скрипт, то произойдет сбой с Uncaught ReferenceError: ключи не определены
Показать ещё 2 комментария
9

Что-то вроде этого -

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--; }}
}
7

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

var myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
6

<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>
<p style="font-size:0.6em;">P.S.: If you want to learn Python and have fun go here <a href="https://pythonprogramming.altervista.org/">https://pythonprogramming.altervista.org/</a>
</p>

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

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

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

  • Запустите либо Object.keys(), чтобы получить массив, содержащий имена только тех свойств, которые перечисляемый или Object.getOwnPropertyNames(), если вы хотите также включить имена свойств, которые не перечислены.
  • Получить свойство .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

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

6

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

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

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

5

Здесь другая версия ответа Джеймса Когана. Вместо передачи аргумента просто создайте прототип класса 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 - плохая идея.
  • 0
    @tborychowski Не могли бы вы объяснить, почему?
Показать ещё 1 комментарий
4

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

Object.keys(myobject).length

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

  • 1
    Похоже, это просто повторение этого существующего ответа .
  • 0
    @Pang согласился, и он не дает никакого дополнительного контекста, как другие ответы.
4

Вы можете просто использовать 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 ?
  • 0
    Это потому, что он показывает, как сделать его как функцию и метод глобального объекта (более объектно-ориентированный и использует некоторую форму инкапсуляции); Однако ответ Aeosynth не.
3
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
3

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

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

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

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

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

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

Давал бы 1.

  • 0
    не отличная идея модифицировать прототип :)
2

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

Object.values(myObject).length
2

Недвижимость

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
2

Как и большинство проблем с 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());
  • 0
    не модифицируйте прототип :)
  • 2
    Модификация прототипа фабричной функции - это способ их расширения.
2

Ниже приведена версия ответа Джеймса Коглана в 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 и не помечался как таковой. Это неверный ответ на вопрос.
0
var obj = {
    key1: "value1",
    key2: "value2",
    key3: "value3"
  }
 // use any of these to find object length
 * Object.keys(obj).length
 * Object.values(obj).length
 * Object.entries(obj).length
0

В лучшем случае, на мой взгляд, if (obj.hasOwnProperty(key)) элемент управления является избыточным. Возвращает всегда true.

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
     size++;
   }
   return size;
};
  • 0
    Это неверно и вводит в заблуждение. Если вы не понимаете, почему код написан так, как есть, не меняйте его. Вместо этого попытайтесь найти методы и понять, что они делают. Причина, по которой hasOwnProperty используется, состоит в том, чтобы предотвратить подсчет ключей в его прототипе. Пример: parent = {a: 1, b:2}; child = Object.create(parent); Object.keys(child) === 0; Object.size(child) === 2; , Это использует ваш Object.size , а не правильный.
0

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

код

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

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

  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

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

var size = JSON.stringify(myObject).length;

document.write(size);

JSON.stringify(myObject)
  • 0
    вопрос решен вокруг количества свойств. Ваш ответ просто показывает, какова длина одной (из многих!) сериализованных форм.
-7

Если вы используете jQuery, просто перейдите к методу .length.

$(object).length даст вам длину переданного объекта.

UPDATE. Это всегда будет возвращать 1 в случае объекта. Но хорошо работает с элементом jQuery.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню