Довжина об’єкта JavaScript


2383

У мене об’єкт 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? Це повертає правильний результат для мене.
Адріан М

Відповіді:


2623

Найбільш надійною відповіддю (тобто, що фіксує наміри того, що ви намагаєтеся зробити, викликаючи найменше помилок) буде:

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
Лукас Ліесіс

1705

Якщо ви знаєте, що не потрібно турбуватися про hasOwnPropertyчеки, це можна зробити дуже просто:

Object.keys(myArray).length

23
чому ні? з того, що я знаю, це стандарт: developer.mozilla.org/uk/JavaScript/Reference/Global_Objects/…
vsync

104
Це не універсально реалізований метод, але ви можете перевірити, який браузер підтримує його за допомогою цієї таблиці .
аеосинтез

51
Немає підтримки IE8 = не йде.
ripper234

22
час перейти на firefox = на жаль, переключення не означає, що користувачі вашого веб-сайту будуть ...
mdup

82
@ ripper234 немає підтримки IE = час на заповнення
Джон Дворак

287

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

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

Якщо ні , і ви не хочете возитися з властивостями Object з будь-якої причини, і вже використовуєте 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.
tokyovariable

4
Я використовую підкреслення, і ця публікація просто нагадала мені, що я недостатньо використовую її в цьому проекті. Якщо ви обробляєте об'єкти, у вас повинен бути наявний underscore.js.
jbolanos

3
Підкреслення> (усі - ['lo-dash'])
Rayjax

підкресли, речі, які мають бути під js :)
minhajul

1
@Babydead для розрізнення реальних властивостей об'єкта від успадкованих. developer.mozilla.org/uk/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;

6
Object.keys()повертає масив, який містить імена лише тих властивостей, які перелічуються. Якщо ви хочете масив із ВСІМ властивостями, вам слід скористатися Object.getOwnPropertyNames()натомість. Дивіться developer.mozilla.org/uk/docs/Web/JavaScript/Reference/…
Джон Slegers

35

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

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

@palmsey: Справедливо до OP, документація JavaScript фактично посилається на використання змінних типу Object таким чином як "асоціативні масиви".


8
Не буде працювати, тому що він також буде рахувати методи, які додаються через прототип.
Лайош Мецарос

30

Цей метод отримує всі назви властивостей вашого об’єкта в масиві, тому ви можете отримати довжину цього масиву, яка дорівнює довжині ключів вашого об'єкта.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2

Метод ключів @PatrickRoberts не повертає властивості з ланцюга прототипу. Так чому тут потрібна власна власність. Також getOwnProperty поверне приховані властивості, оскільки довжина знаходиться в масиві тощо.
Muhammad Umer

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

Якщо ви завжди використовуєте метод додавання, властивість length буде правильним. Якщо ви переживаєте, що ви або інші забули про його використання, ви можете додати лічильник властивостей, який інші розмістили до методу довжини.

Звичайно, ви завжди можете перезаписати методи. Але навіть якщо ви це зробите, ваш код, ймовірно, помітно вийде з ладу, що спрощує налагодження. ;)


Я думаю, що це найкраще рішення, оскільки воно не вимагає циклу з "за", що може бути дорогим, якщо масив великий
Emeka Mbah

20

Ось як і не забудьте перевірити, чи властивість не в ланцюзі прототипу:

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

20

Просто використовуйте це, щоб отримати length:

Object.keys(myObject).length

7
будь ласка , поясніть , як ваша відповідь відрізняється від stackoverflow.com/a/6700/8632727
Patata

3
Ви також не повинні називати ваш об'єктmyArray
Баррі Майкл Дойл

2
@BarryMichaelDoyle я змінив це :)
saurabhgoyal795

Добре, завжди краще називати свої змінні відповідно до того, якими вони є насправді. Робить ваш код більш читабельним для інших розробників.
Баррі Майкл Дойл

4
Перш ніж редагувати "myArray" -> "myObject", це було ідентично другій відповіді, що найбільше підтримує.
Yunnosch

16

Ось зовсім інше рішення, яке працюватиме лише в більш сучасних браузерах (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);

Я думаю, що це не безпечно. Наприклад, він не може мати елемент з ключем "length", вираз a1 ["length"] = "Hello world"; не вдалося зберегти запис. Також оператор a1 ["hasOwnProperty"] = "деяка опора"; загалом порушує функцію
Панос Теоф

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;

15

У деяких випадках розмір краще просто зберігати в окремій змінній. Тим більше, якщо ви додаєте до масиву по одному елементу в одному місці і можете легко збільшити розмір. Очевидно, це буде працювати набагато швидше, якщо вам потрібно часто перевіряти розмір.



14

@palmsey: Справедливо до OP, документи JavaScript фактично прямо посилаються на використання змінних типу Object таким чином як "асоціативні масиви".

І справедливо до @palmsey він виявився цілком коректним, вони не асоціативні масиви, вони, безумовно, об'єкти :) - виконуючи роботу асоціативного масиву. Але що стосується більш широкого пункту, ви, безумовно, маєте право на це відповідно до цієї досить чудової статті, яку я знайшов:

JavaScript "Асоціативні масиви" вважається шкідливим

Але відповідно до всього цього, чи не є прийнятою відповіддю самою поганою практикою?

Вкажіть функцію розміру прототипу () для 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 і перевірити тип членів під час їх перегляду.


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

ми можемо отримати довжину, використовуючи довжину ключів, яка є довжиною хеша:

ключі (хеш). довжина


2
Це чудова відповідь, проте я не можу знайти жодної документації для цієї функції клавіш. Тому я не можу бути впевненим у підтримці крос-браузера.
шим

1
На жаль, це не така гарна відповідь, як я вперше подумав! Виявляється, функція клавіш доступна лише у веб-консолях chrome та firefox. Якщо ви вкладете цей код у сценарій, він не зможе виконати програму Uncaught ReferenceError: ключі не визначені
підкажіть


1
Чим це відрізняється від відповіді аеосинтезу ?
Пітер Мортенсен

11
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
  1. Object.values ​​(myObject) .length
  2. Object.entries (myObject). Довжина
  3. Object.keys (myObject). Довжина

Хто швидше серед вищезгаданих 3.
siluveru kiran kumar

Object.values ​​(myObject) .length
tdjprog

як ми можемо сказати, що це Object.values ​​(myObject) .length швидше, чи є приклад Спасибі, @tdjprog
siluveru kiran kumar

просто спробуйте це в консолі:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog

чому Object.values ​​(myObject) .length швидше, де як Object.entries (myObject) .length не дає результату навіть після чогось, в чому причина? Дякуємо @tdjprog
siluveru kiran kumar

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>

4
ОП не вимагає версії AngularJS. Це неправдива відповідь на питання.
Франсіско Ходж

10

Найпростіший спосіб такий

Object.keys(myobject).length

де мій об’єкт є об’єктом того, що потрібно довжина


2
Це, здається, є лише повторенням цієї відповіді .
Панг

@ Панг погодився, і це не надає жодного подальшого контексту, як це роблять інші відповіді.
Містичний

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

Дивіться також цей Fiddle для демонстрації.


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

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

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

// o/p 3

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- погана ідея.
Dziad Borowy

@tborychowski чи можете ви поясніть чому?
Мухаммад

ось одна стаття: bit.ly/1droWrG . Я не кажу, що це не повинно бути зроблено, тільки що вам потрібно знати всі наслідки, перш ніж це зробити.
Dziad Borowy

Якщо ви збираєтеся розширювати вбудовані прототипи або поліфікувати властивість (тобто мавпа-патч), будь ласка, зробіть це правильно: для сумісності вперед перевірте, чи властивість існує спочатку, а потім зробіть властивість нечисленною, щоб власні ключі споруджені об'єкти не забруднюються. Для методів використовують фактичні методи . Моя рекомендація: дотримуйтесь цих прикладів, які демонструють, як додати метод, який поводиться максимально близько, як вбудовані методи.
user4642212

5

Ви можете просто використовувати Object.keys(obj).lengthбудь-який об’єкт, щоб отримати його довжину. Object.keys повертає масив, що містить усі об'єктні ключі (властивості), які можуть стати в нагоді для пошуку довжини цього об'єкта, використовуючи довжину відповідного масиву. Ви навіть можете написати функцію для цього. Давайте проявимо креативність і напишемо метод для цього (разом із більш зручним властивістю отримання):

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
Чим це відрізняється від відповіді аеосинтезу ?
Пітер Мортенсен

Це тому, що він показує, як зробити його як функцію та глобальний метод об'єкта (більш об'єктно орієнтований та використовує певну форму капсулювання); однак відповідь аеосинта не відповідає .
Містичний

Якщо ви збираєтеся розширювати вбудовані прототипи або поліфікувати властивість (тобто мавпа-патч), будь ласка, зробіть це правильно: для сумісності вперед перевірте, чи існує властивість спочатку, а потім зробіть властивість нечисленною, щоб власні ключі споруджені об'єкти не забруднюються. Для методів використовують фактичні методи . Моя рекомендація: дотримуйтесь цих прикладів, які демонструють, як додати метод, який поводиться максимально близько, як вбудовані методи.
користувач4642212

Крім того, як писати метод "більш ефективним"?
користувач4642212

5

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


1
Object.keys()повертає масив, який містить імена лише тих властивостей, які перелічуються. Якщо ви хочете масив із ВСІМ властивостями, вам слід скористатися Object.getOwnPropertyNames()натомість. Дивіться developer.mozilla.org/uk/docs/Web/JavaScript/Reference/…
Джон Slegers

3
Чим це відрізняється від відповіді аеосинтезу ?
Пітер Мортенсен


4

Трохи запізнюється в грі, але приємний спосіб досягти цього (лише IE9 +) - це визначити магічний гетьтер у властивості довжини:

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

І ви можете просто використовувати його так:

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

Дав би 1.


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 і не позначений як такий. Це неправдива відповідь на питання.
Франсиско Ходж
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.