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

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

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

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

30 ответов

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

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

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

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

    var element_count = 0;
    for(var e in myArray)
        if(myArray.hasOwnProperty(e))
            element_count++;
    
  3. @palmsey: справедливости ради, документы javascript фактически явно ссылаются на использование переменных типа Object таким образом как «ассоциативные массивы».

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

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

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

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

    Если что-то еще было добавлено в объект .прототип, после этого предложенный код потерпит неудачу:

    <script type="text/javascript">
    Object.prototype.size = function () {
    &nbsp; var len = this.length ? --this.length : -1;
    &nbsp; &nbsp; for (var k in this)
    &nbsp; &nbsp; &nbsp; len++;
    &nbsp; return len;
    }
    Object.prototype.size2 = function () {
    &nbsp; var len = this.length ? --this.length : -1;
    &nbsp; &nbsp; for (var k in this)
    &nbsp; &nbsp; &nbsp; len++;
    &nbsp; 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 и проверить тип элементов, когда вы повторяете их.

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

    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, что вы не добавляете вещи в объект.прототип, поскольку он может разбивать перечисления в различных библиотеках. Однако добавление методов к объекту обычно безопасно.


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

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

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

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

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

    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
    
  5. Если вы знаете, что вам не нужно беспокоиться о hasOwnPropertyпроверках, вы можете сделать это очень просто:

    Object.keys(myArray).length
    
  6. Чтобы не связываться с прототипом или другим кодом, можно создать и расширить собственный объект:

    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.

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

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

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

    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--; }}
    }
    
  9. Вариация на некоторые из вышеперечисленных:

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

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

  10. Обновлено: если вы используете подчеркивание.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;
    };
    
  11. Ниже представлена версия James Coglan’s answer in CoffeeScript для тех, кто отказался от прямого JavaScript 🙂

    Object.size = (obj) ->
      size = 0
      size++ for own key of obj
      size
    
  12. Вот другая версия ответа Джеймса Когана. Вместо передачи аргумента просто создайте прототип класса 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/

  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);
    
  14. Вот самое кроссбраузерное решение.

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

    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;
    
  15. Если у нас есть гашиш

    hash = {«a»: «b»,» c»: «d»};

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

    ключи (хэш).длина

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

    Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
    
  17. Свойство

    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
    
  18. Если вы используете 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>
    
  19. Вы всегда можете сделать Object.getOwnPropertyNames(myObject).lengthтак, чтобы получить тот же результат, [].lengthчто и для обычного массива.

  20. Если вы не заботитесь о поддержке 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
    

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

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

    var myMap = new Map();
    myMap.set("firstname", "Gareth");
    myMap.set("lastname", "Simpson");
    myMap.set("age", 21);
    myMap.size; // 3
    
  22. Вы можете просто использовать Object.keys(obj).lengthна любом объекте, чтобы получить его длину. Объект.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()

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

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

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

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

    Дадут 1.

  24. var myObject = new Object();
    myObject["firstname"] = "Gareth";
    myObject["lastname"] = "Simpson";
    myObject["age"] = 21;
    
    1. Объект.значения (myObject).длина
    2. Объект.записи (myObject).длина
    3. Объект.ключи (myObject).длина
  25. <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;