Bagaimana cara mengulangi objek JavaScript?

422

Saya memiliki objek dalam JavaScript:

{
    abc: '...',
    bca: '...',
    zzz: '...',
    xxx: '...',
    ccc: '...',
    // ...
}

Saya ingin menggunakan forloop untuk mendapatkan propertinya. Dan saya ingin mengulanginya di bagian-bagian (tidak semua properti objek sekaligus).

Dengan array sederhana saya bisa melakukannya dengan forloop standar :

for (i = 0; i < 100; i++) { ... } // first part
for (i = 100; i < 300; i++) { ... } // second
for (i = 300; i < arr.length; i++) { ... } // last

Tetapi bagaimana melakukannya dengan benda?

nkuhta
sumber
22
Ingatlah bahwa properti objek tidak disimpan secara berurutan. Ketika Anda beralih pada suatu objek tidak ada jaminan untuk urutan di mana mereka akan muncul.
James Allardice

Jawaban:

851

Untuk sebagian besar objek, gunakan for .. in:

for (let key in yourobject) {
  console.log(key, yourobject[key]);
}

Dengan ES6, jika Anda membutuhkan kedua kunci dan nilai secara bersamaan, lakukan

for (let [key, value] of Object.entries(yourobject)) {
    console.log(key, value);
}

Untuk menghindari logging properti yang diwarisi, tanyakan dengan hasOwnProperty :

for (let key in yourobject) {
   if (yourobject.hasOwnProperty(key)) {
      console.log(key, yourobject[key]);
   }
}

Anda tidak perlu memeriksa hasOwnPropertysaat iterasi tombol-tombol jika Anda menggunakan objek sederhana (misalnya objek yang Anda buat sendiri {}).

Dokumentasi MDN ini menjelaskan secara lebih umum bagaimana menangani objek dan propertinya.

Jika Anda ingin melakukannya "dalam potongan", yang terbaik adalah mengekstrak kunci dalam sebuah array. Karena pesanan tidak dijamin, ini adalah cara yang tepat. Di browser modern, Anda dapat menggunakan

let keys = Object.keys(yourobject);

Agar lebih kompatibel, Anda sebaiknya melakukan ini:

 let keys = [];
 for (let key in yourobject) {      
     if (yourobject.hasOwnProperty(key)) keys.push(key);
 }

Kemudian Anda dapat mengulangi properti Anda dengan indeks yourobject[keys[i]]::

for (let i=300; i < keys.length && i < 600; i++) { 
   console.log(keys[i], yourobject[keys[i]]);
}
Denys Séguret
sumber
3
OP ingin melakukan ini dalam potongan, tidak semua kunci dalam satu lingkaran.
pawel
Iya. Bukan objek penuh dalam satu loop.
nkuhta
2
@Cerbrus OP allready tahu cara mengulang array di bagian-bagian. Menggunakan keysdari kode yang diberikan harus cukup.
Yoshi
2
@Cerbrus Harap baca sebelum berkomentar! Apa yang tidak jelas dalam "Agar lebih kompatibel, Anda sebaiknya melakukan ini" ?
Denys Séguret
2
@ am05mhz Seperti yang saya katakan, tidak berguna dengan sebagian besar objek. Tapi tidak untuk semua. Coba ini: jsbin.com/hirivubuta/1/edit?js,console,output
Denys Séguret
61

Berikut ini adalah solusi iterasi untuk peramban modern:

Object.keys(obj)
  .filter((k, i) => i >= 100 && i < 300)
  .forEach(k => console.log(obj[k]));

Atau tanpa fungsi filter:

Object.keys(obj).forEach((k, i) => {
    if (i >= 100 && i < 300) {
        console.log(obj[k]);
    }
});

Namun Anda harus mempertimbangkan bahwa properti dalam objek JavaScript tidak diurutkan, yaitu tidak memiliki urutan.

Penglihatan
sumber
Jika saya akan memutus loop, itu akan mulai dari awal objek waktu berikutnya, itu bukan cara yang benar.
nkuhta
21

Menggunakan Object.entriesAnda melakukan sesuatu seperti ini.

 // array like object with random key ordering
 const anObj = { 100: 'a', 2: 'b', 7: 'c' };
 console.log(Object.entries(anObj)); // [ ['2', 'b'],['7', 'c'],['100', 'a'] ]

Metode Object.entries () mengembalikan array properti enumerable milik objek tertentu [kunci, nilai]

Jadi Anda dapat beralih di atas Obyek dan memiliki keydan valueuntuk masing-masing objek dan mendapatkan sesuatu seperti ini.

const anObj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(anObj).map(obj => {
   const key   = obj[0];
   const value = obj[1];

   // do whatever you want with those values.
});

atau seperti ini

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

Untuk referensi, lihat dokumen MDN untuk Entri Objek

Adeel Imran
sumber
18

Dengan fitur ES6 / ES2015 yang baru, Anda tidak perlu lagi menggunakan objek untuk beralih pada hash. Anda bisa menggunakan Peta . Javascript Maps menyimpan kunci dalam urutan penyisipan, artinya Anda dapat mengulanginya tanpa harus memeriksa hasOwnProperty, yang selalu benar-benar merupakan peretasan.

Iterate di atas peta:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

for (var key of myMap.keys()) {
  console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"

for (var value of myMap.values()) {
  console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

atau gunakan forEach:

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
Paul
sumber
1
forEach adalah yang lebih disukai
pungggi
14

Jika Anda ingin kunci dan nilai saat iterasi, Anda bisa menggunakan for ... of loop dengan Object.entries .

const myObj = {a: 1, b: 2}

for (let [key, value] of Object.entries(myObj)) {
    console.log(`key=${key} value=${value}`)
}

// output: 
// key=a value=1
// key=b value=2
Derek Soike
sumber
7

Satu-satunya cara yang dapat diandalkan untuk melakukan ini adalah menyimpan data objek Anda ke 2 array, satu kunci, dan satu untuk data:

var keys = [];
var data = [];
for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        keys.push(key);
        data.push(obj[key]); // Not necessary, but cleaner, in my opinion. See the example below.
    }
}

Anda kemudian dapat mengulangi susunan seperti biasanya:

for(var i = 0; i < 100; i++){
    console.log(keys[i], data[i]);
    //or
    console.log(keys[i], obj[keys[i]]); // harder to read, I think.
}
for(var i = 100; i < 300; i++){
    console.log(keys[i], data[i]);
}

Saya tidak menggunakan Object.keys(obj), karena itulah IE 9+.

Cerbrus
sumber
3

-> jika kita beralih pada objek JavaScript menggunakan dan menemukan kunci array objek

Object.keys(Array).forEach(key => {

 console.log('key',key)

})
ashishdudhat
sumber
1

Jika Anda ingin mengulang seluruh objek sekaligus, Anda bisa menggunakan for inloop:

for (var i in obj) {
  ...
}

Tetapi jika Anda ingin membagi objek menjadi beberapa bagian sebenarnya Anda tidak bisa. Tidak ada jaminan bahwa properti di objek berada dalam urutan tertentu. Karena itu, saya dapat memikirkan dua solusi.

Pertama-tama adalah "menghapus" properti yang sudah dibaca:

var i = 0;
for (var key in obj) {
    console.log(obj[key]);
    delete obj[key];
    if ( ++i > 300) break;
}

Solusi lain yang dapat saya pikirkan adalah dengan menggunakan Array of Arays alih-alih objek:

var obj = [['key1', 'value1'], ['key2', 'value2']];

Kemudian, forloop standar akan berfungsi.

Michał Miszczyszyn
sumber
1

Saya akhirnya datang dengan fungsi utilitas praktis dengan antarmuka terpadu untuk beralih Objek, Strings, Array, TypedArrays, Maps, Sets, (any Iterables).

const iterate = require('@a-z/iterate-it');
const obj = { a: 1, b: 2, c: 3 };

iterate(obj, (value, key) => console.log(key, value)); 
// a 1
// b 2
// c 3

https://github.com/alrik/iterate-javascript

Alrik Zachert
sumber
1

Anda dapat mencoba menggunakan lodash- Pustaka utilitas JavaScript modern yang menghadirkan modularitas, kinerja & ekstra untuk mempercepat objek:

var  users  =   {
    'fred':     { 
        'user':   'fred',
            'age':  40 
    },
    'pebbles':  { 
        'user':   'pebbles',
         'age':  1 
    }
}; 
_.mapValues(users,  function(o)  { 
    return  o.age; 
});
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
console.log(_.mapValues(users,  'age')); // returns age property & value 
console.log(_.mapValues(users,  'user')); // returns user property & value 
console.log(_.mapValues(users)); // returns all objects 
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.js"></script>

Parth Raval
sumber
1

Untuk iterasi objek biasanya kita menggunakan for..inloop. Struktur ini akan berulang melalui semua properti enumerable , termasuk yang diwariskan melalui pewarisan prototypal. Sebagai contoh:

let obj = {
  prop1: '1',
  prop2: '2'
}

for(let el in obj) {
  console.log(el);
  console.log(obj[el]);
}

Namun, for..inakan mengulang semua elemen yang dapat dihitung dan ini tidak akan dapat memisahkan iterasi menjadi potongan. Untuk mencapai ini, kita dapat menggunakan Object.keys()fungsi bawaan untuk mengambil semua kunci dari suatu objek dalam array. Kami kemudian dapat membagi iterasi menjadi beberapa untuk loop dan mengakses properti menggunakan array kunci. Sebagai contoh:

let obj = {
  prop1: '1',
  prop2: '2',
  prop3: '3',
  prop4: '4',
};

const keys = Object.keys(obj);
console.log(keys);


for (let i = 0; i < 2; i++) {
  console.log(obj[keys[i]]);
}


for (let i = 2; i < 4; i++) {
  console.log(obj[keys[i]]);
}

Willem van der Veen
sumber
0
var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);
HovyTech
sumber
1
Sebenarnya tidak. Ini menyiratkan bahwa Objects tidak berurutan. Mereka tidak. If you can make sense of the sentence it workedhanya berfungsi karena detail implementasi. Tidak dijamin untuk bekerja sama sekali. Anda juga tidak seharusnya TitleCase fungsi & variabel Anda. Itu untuk classes.
Florian Wendelborn
0

Benar-benar PITA ini bukan bagian dari Javascript standar.

/**
 * Iterates the keys and values of an object.  Object.keys is used to extract the keys.
 * @param object The object to iterate
 * @param fn (value,key)=>{}
 */
function objectForEach(object, fn) {
    Object.keys(object).forEach(key => {
        fn(object[key],key, object)
    })
}

Catatan: Saya mengalihkan parameter panggilan balik ke (nilai, kunci) dan menambahkan objek ketiga untuk membuat API konsisten dengan API lainnya.

Gunakan seperti ini

const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
    // do something
});
Steven Spungin
sumber
1
dibatalkan hanya untuk pernyataan Anda di kalimat pertama. Meskipun akan lebih baik jika nilainya parameter pertama, parameter indeks atau kunci kedua, dan parameter objek ketiga, untuk membuatnya lebih seperti array forEach (). Saya akan merekomendasikan merekomendasikan lodash.
KONTRAK MENGATAKAN AKU BENAR
Saya suka gagasan urutan (nilai, kunci). Begitulah cara perpustakaan seperti Vue melakukannya juga. Karena objek adalah konteksnya, objek itu menganggapnya sebagai parameter pertama. Itu cukup standar untuk pemrograman fungsional.
Steven Spungin
Saya setuju di sini, jika ECMA-262 tidak mendefinisikan array sebagai objek yang memiliki forEach (), map (), kurangi (), filter (), yang semuanya menerima panggilan balik yang menerima pesanan [nilai, indeks, array] . Objek di JS dapat dipahami hanya sebagai koleksi lain; dan kemudian metode ini menjadi satu dalam parameter [nilai, kunci | indeks, konteks] mereka (inilah yang dilakukan oleh lodash dan garis bawah). Menurut pendapat saya, protokol "koleksi terpadu" ini hanya lebih kuat. Selain itu, objeknya bukan konteksnya: Anda dapat mengatur thisapa pun yang Anda suka untuk panggilan balik, karena panggilan balik itu memiliki konteksnya sendiri.
KONTRAK MENGATAKAN AKU BENAR
Mungkin saya seharusnya menggunakan receiver kantor daripada ini. Pokoknya masih PITA; Saya akan menyambut parameter dalam urutan apa pun.
Steven Spungin
Oh, saya melihat bahwa kita mungkin telah salah mengerti satu sama lain. Saya selalu berkomentar tentang parameter panggilan balik dan urutannya, bukan tentang objectForEachfungsi sebenarnya . Maaf kalau itu membingungkan.
KONTRAK MENGATAKAN SAYA BENAR
0

Iya. Anda bisa mengulang melalui objek menggunakan untuk loop. Berikut ini sebuah contoh

var myObj = {
    abc: 'ABC',
    bca: 'BCA',
    zzz: 'ZZZ',
    xxx: 'XXX',
    ccc: 'CCC',
}

var k = Object.keys (myObj);
for (var i = 0; i < k.length; i++) {
    console.log (k[i] + ": " + myObj[k[i]]);
}

CATATAN: contoh yang disebutkan di atas hanya akan berfungsi di IE9 +. Lihat dukungan browser Objec.keys di sini .

Omprakash Arumugam
sumber
0
const o = {
  name: "Max",
  location: "London"
};

for (const [key, value] of Object.entries(o)) {
  console.log(`${key}: ${value}`);
}

Coba online

Vishal
sumber