Pertanyaan Bagaimana cara menghitung jumlah kunci / properti suatu objek dalam JavaScript secara efisien?


Apa cara tercepat untuk menghitung jumlah kunci / properti suatu objek? Apakah mungkin untuk melakukan ini tanpa melakukan iterasi terhadap objek? yaitu tanpa melakukan

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;

(Firefox memang memberikan keajaiban __count__ properti, tetapi ini dihapus di suatu tempat di sekitar versi 4.)


1192
2017-09-24 08:56


asal


Jawaban:


Untuk melakukan ini di lingkungan yang kompatibel dengan ES5, seperti Node, Chrome, IE 9+, FF 4+, atau Safari 5+:

Object.keys(obj).length

1982
2018-02-03 17:47



Anda bisa menggunakan kode ini:

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

Kemudian Anda dapat menggunakan ini di browser lama juga:

var len = Object.keys(obj).length;

140
2018-04-15 10:48



Jika Anda menggunakan Underscore.js Kamu dapat memakai _.ukuran (terima kasih @douwe):
_.size(obj)

Atau Anda juga bisa menggunakan _.kunci yang mungkin lebih jelas untuk beberapa:
_.keys(obj).length 

Saya sangat merekomendasikan Underscore, perpustakaan yang ketat untuk melakukan banyak hal dasar. Kapan pun mereka cocok dengan ECMA5 dan tunduk pada implementasi asli.

Kalau tidak, saya mendukung jawaban @ Avi. Saya mengeditnya untuk menambahkan tautan ke dokumen MDC yang menyertakan metode kunci () yang dapat Anda tambahkan ke browser non-ECMA5.


126
2018-05-16 15:24



Implementasi standar objek (ES5.1 Obyek Properti Internal dan Metode) tidak membutuhkan Object untuk melacak jumlah kunci / propertinya, sehingga seharusnya tidak ada cara standar untuk menentukan ukuran Object tanpa secara eksplisit atau implisit iterasi atas kunci-kuncinya.

Jadi di sini adalah alternatif yang paling umum digunakan:

1. Objek Objects ECMAScript ()

Object.keys(obj).length; Bekerja oleh secara internal iterasi atas kunci untuk menghitung array sementara dan mengembalikan panjangnya.

  • Pro - Sintaks yang bisa dibaca dan bersih. Tidak ada pustaka atau kode khusus yang diperlukan kecuali shim jika dukungan asli tidak tersedia
  • Cons - Memori overhead karena pembuatan array.

2. Solusi berbasis perpustakaan

Banyak contoh berbasis pustaka di tempat lain dalam topik ini adalah idiom yang berguna dalam konteks pustaka mereka. Namun, dari sudut pandang kinerja, tidak ada yang dapat diperoleh dibandingkan dengan kode no-library yang sempurna karena semua metode pustaka tersebut benar-benar mengenkapsulasi baik untuk loop atau ES5 Object.keys (asli atau shimmed).

3. Mengoptimalkan for-loop

Itu bagian paling lambat seperti for-loop umumnya .hasOwnProperty() panggilan, karena fungsi panggilan overhead. Jadi, ketika saya hanya ingin jumlah entri objek JSON, saya hanya melewatkan .hasOwnProperty() panggil jika saya tahu bahwa tidak ada kode yang juga tidak akan diperpanjang Object.prototype.

Jika tidak, kode Anda bisa sangat sedikit dioptimalkan dengan membuat k lokal (var k) dan dengan menggunakan operator penambahan-awal (++count) bukan postfix.

var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

Ide lain bergantung pada caching hasOwnProperty metode:

var hasOwn = Object.prototype.hasOwnProperty;
var count = 0;
for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

Apakah ini lebih cepat atau tidak pada lingkungan tertentu adalah masalah pembandingan. Keuntungan kinerja yang sangat terbatas dapat diharapkan pula.


65
2017-09-24 09:11



Jika Anda benar-benar mengalami masalah kinerja saya akan menyarankan membungkus panggilan yang menambah / menghapus properti ke / dari objek dengan fungsi yang juga menambah / mengurangi properti bernama (ukuran?) Yang tepat.

Anda hanya perlu menghitung jumlah awal properti sekali dan pindah dari sana. Jika tidak ada masalah kinerja yang sebenarnya, jangan repot-repot. Bungkus saja kode itu dalam suatu fungsi getNumberOfProperties(object) dan selesai dengan itu.


23
2017-09-24 09:13



Saya tidak mengetahui cara apa pun untuk melakukan hal ini, namun untuk menjaga iterasinya seminimal mungkin, Anda dapat mencoba memeriksa keberadaan __count__ dan jika tidak ada (yaitu bukan Firefox) maka Anda bisa mengulang objek dan menentukannya untuk digunakan nanti misalnya:

if (myobj.__count__ === undefined) {
  myobj.__count__ = ...
}

Dengan cara ini browser mana saja yang mendukung __count__ akan menggunakannya, dan iterasi hanya akan dilakukan bagi mereka yang tidak. Jika hitungan berubah dan Anda tidak dapat melakukan ini, Anda selalu dapat menjadikannya sebagai fungsi:

if (myobj.__count__ === undefined) {
  myobj.__count__ = function() { return ... }
  myobj.__count__.toString = function() { return this(); }
}

Dengan cara ini kapan saja Anda mereferensikan myobj.__count__ fungsi akan menyala dan menghitung ulang.


15
2018-01-17 11:15



Sebagaimana dinyatakan oleh Avi Flax https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

akan melakukan trik untuk semua properti enumerable pada objek Anda tetapi juga menyertakan properti non-enumerable yang dapat Anda gunakan sebagai gantinya Object.getOwnPropertyNames. Inilah perbedaannya:

var myObject = new Object();

Object.defineProperty(myObject, "nonEnumerableProp", {
  enumerable: false
});
Object.defineProperty(myObject, "enumerableProp", {
  enumerable: true
});

console.log(Object.getOwnPropertyNames(myObject).length); //outputs 2
console.log(Object.keys(myObject).length); //outputs 1

console.log(myObject.hasOwnProperty("nonEnumerableProp")); //outputs true
console.log(myObject.hasOwnProperty("enumerableProp")); //outputs true

console.log("nonEnumerableProp" in myObject); //outputs true
console.log("enumerableProp" in myObject); //outputs true

Sebagaimana dinyatakan sini ini memiliki dukungan browser yang sama dengan Object.keys

Namun, dalam banyak kasus, Anda mungkin tidak ingin menyertakan nonenumerables dalam jenis operasi ini, tetapi selalu baik untuk mengetahui perbedaannya;)


15
2018-03-30 01:11



To itate pada Avi Flax answer Object.keys (obj). Length adalah benar untuk objek yang tidak memiliki fungsi terkait dengannya.

contoh:

obj = {"lol": "what", owo: "pfft"};
Object.keys(obj).length; // should be 2

melawan

arr = [];
obj = {"lol": "what", owo: "pfft"};
obj.omg = function(){
    _.each(obj, function(a){
        arr.push(a);
    });
};
Object.keys(obj).length; // should be 3 because it looks like this 
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

langkah-langkah untuk menghindari ini:

  1. jangan meletakkan fungsi dalam objek yang ingin Anda hitung jumlah kunci

  2. gunakan objek terpisah atau buat objek baru khusus untuk fungsi (jika Anda ingin menghitung berapa banyak fungsi yang ada dalam file menggunakan Object.keys(obj).length)

juga ya saya menggunakan modul _ atau garis bawah dari nodejs dalam contoh saya

dokumentasi dapat ditemukan di sini http://underscorejs.org/ serta sumbernya di github dan berbagai info lainnya

Dan akhirnya penerapan lodash https://lodash.com/docs#size

_.size(obj)


12
2018-01-04 09:04



Bagi mereka yang memiliki Underscore.js termasuk dalam proyek mereka, Anda dapat melakukan:

_({a:'', b:''}).size() // => 2

atau gaya fungsional:

_.size({a:'', b:''}) // => 2

8
2017-08-21 03:37



Dari: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty (obj, prop, deskriptor)

Anda dapat menambahkannya ke semua objek Anda:

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

Atau satu objek tunggal:

var myObj = {};
Object.defineProperty(myObj, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

Contoh:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "leaked@example.com";
myObj.length; //output: 2

Ditambahkan dengan cara itu, itu tidak akan ditampilkan dalam for..in loop:

for(var i in myObj) {
     console.log(i + ":" + myObj[i]);
}

Keluaran:

name:John Doe
email:leaked@example.com

Catatan: itu tidak berfungsi di <IE9 browsers.


6
2018-06-28 10:04



Bagaimana saya mengatasi masalah ini adalah dengan membangun implementasi saya sendiri dari daftar dasar yang menyimpan catatan berapa banyak item yang disimpan dalam objek. Ini sangat sederhana. Sesuatu seperti ini:

function BasicList()
{
   var items = {};
   this.count = 0;

   this.add = function(index, item)
   {
      items[index] = item;
      this.count++;
   }

   this.remove = function (index)
   {
      delete items[index];
      this.count--;
   }

   this.get = function(index)
   {
      if (undefined === index)
        return items;
      else
        return items[index];
   }
}

5
2018-04-12 07:40