Bagaimana cara saya mengulang atau menyebutkan objek JavaScript?

2880

Saya memiliki objek JavaScript seperti berikut:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Sekarang saya ingin loop melalui semua pelemen ( p1, p2, p3...) dan mendapatkan kunci dan nilai-nilai mereka. Bagaimana saya bisa melakukan itu?

Saya dapat memodifikasi objek JavaScript jika perlu. Tujuan utama saya adalah untuk mengulangi beberapa pasangan nilai kunci dan jika mungkin saya ingin menghindari penggunaan eval.

Tanmoy
sumber
9
Saya mengubah JSON menjadi JavaScript (objek) untuk menghindari kebingungan literal objek dan JSON.
Felix Kling

Jawaban:

4367

Anda dapat menggunakan for-inloop seperti yang ditunjukkan oleh orang lain. Namun, Anda juga harus memastikan bahwa kunci yang Anda dapatkan adalah properti sebenarnya dari suatu objek, dan tidak berasal dari prototipe.

Berikut cuplikannya:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

Alternatif untuk-dengan Object.keys ():

var p = {
    0: "value1",
    "b": "value2",
    key: "value3"
};

for (var key of Object.keys(p)) {
    console.log(key + " -> " + p[key])
}

Perhatikan penggunaan for-ofalih - alih for-in, jika tidak digunakan akan kembali tidak ditentukan pada properti bernama, dan Object.keys()memastikan penggunaan hanya properti objek sendiri tanpa seluruh properti rantai prototipe

Menggunakan Object.entries()metode baru :

Catatan: Metode ini tidak didukung secara native oleh Internet Explorer. Anda dapat mempertimbangkan menggunakan Polyfill untuk browser lama.

const p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}
levik
sumber
34
Saya sarankan Anda mengubah jalur peringatan hanya untuk kejelasanalert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley
80
Bisakah Anda menjelaskan perlunya hasOwnProperty? Apa yang Anda maksud dengan prototipe?
kamaci
331
Dalam javascript, setiap objek memiliki sekelompok pasangan nilai kunci bawaan yang memiliki informasi meta. Saat Anda menggilir semua pasangan nilai kunci untuk objek yang Anda lewati juga. hasOwnPropery () menyaring ini.
danieltalsky
57
Sebenarnya, Untuk ... di tidak ditinggalkan. Untuk setiap ... masuk adalah. Tapi saya sangat suka istilah arkeolog ... Saya harus mulai menggunakan itu.
Ben Y
17
setiap objek dalam javascript (sebenarnya pasangan kunci-nilai) memiliki properti yang disebut __proto__atau prototype. Properti ini memiliki referensi ke objek induknya. Objek secara otomatis mewarisi properti dari induknya. Ini adalah alasan penggunaan hasOwnProperty, yang menandakan bahwa kami tertarik pada objek yang memiliki properti dan bukan properti induknya.
Zubair Alam
1104

Di bawah ECMAScript 5, Anda dapat menggabungkan Object.keys()dan Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ECMAScript 6 menambahkan for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ECMAScript 8 menambahkan Object.entries()yang menghindari keharusan mencari setiap nilai dalam objek asli:

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

Anda dapat menggabungkan for...of, merusak, dan Object.entries:

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

Keduanya Object.keys()dan Object.entries()iterasi properti dalam urutan yang sama seperti for...inloop tetapi abaikan rantai prototipe . Hanya properti enumerable objek sendiri yang diulang.

Axel Rauschmayer
sumber
21
Mengapa standar tidak menyediakan Object.forEach(obj, function (value, key) {...})? :( Tentu saja obj.forEach(function...)akan lebih pendek dan komplemen Array.prototype.forEach, tetapi itu akan berisiko memiliki objek menentukan forEachproperti mereka sendiri . Saya kira Object.keyspenjaga terhadap panggilan balik memodifikasi kunci objek.
David Harkness
7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness
7
@ Davidvidark Ada Object.entries di ES2017. Di sana Anda dapat melakukan hal-hal berikut: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([kunci, nilai] adalah destruksi array, untuk mengakses kedua item secara langsung. Dan Anda harus membungkus parameter dalam parens tambahan.)
Andreas Linnert
bagaimana cara mendapatkan indexkunci di json? Atau jika perlu saya harus menggunakan penghitung yang terpisah?
Saravanabalagi Ramachandran
3
for...ofadalah standar ES6, bukan ES2016.
Rax Weber
342

Anda harus menggunakan for-in loop

Tetapi berhati-hatilah saat menggunakan loop semacam ini, karena ini akan mengulang semua properti di sepanjang rantai prototipe .

Oleh karena itu, saat menggunakan loop for-in, selalu gunakan hasOwnPropertymetode ini untuk menentukan apakah properti saat ini dalam iterasi benar-benar properti objek yang Anda periksa:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}
Andreas Grech
sumber
31
Ini lebih baik daripada solusi levik karena memungkinkan logika utama hanya satu loop bersarang daripada dua; membuat kode lebih mudah dibaca. Meskipun saya kehilangan tanda kurung di sekitar melanjutkan; mereka berlebihan.
SystemicPlural
52
Saya tidak akan menghapus { }secara pribadi karena iftanpa mereka membuatnya sedikit tidak jelas apa yang menjadi bagian ifdan apa yang tidak. Tapi saya kira itu hanya masalah pendapat :)
pimvdb
34
Ya, saya lebih suka menjaga { }terutama untuk menghindari kebingungan jika nanti perlu menambahkan sesuatu ke ifruang lingkup.
Andreas Grech
8
Membaca komentar saya sebelumnya, saya menyadari bahwa saya tidak menggunakan istilah yang benar, karena saya mengatakan "jika ruang lingkup"; tetapi perlu diingat bahwa JavaScript hanya memiliki lingkup fungsi. Jadi yang saya maksud sebenarnya adalah "jika blok".
Andreas Grech
1
eomeroff, jika Anda benar-benar khawatir tentang itu, Anda selalu dapat melakukan sesuatu seperti: Object.prototype.hasOwnProperty.call(p, prop) Namun, ini juga tidak dapat melindungi terhadap manipulasi Object.prototype ...
jordancpaul
252

Pertanyaan tidak akan lengkap jika kita tidak menyebutkan tentang metode alternatif untuk perulangan melalui objek.

Saat ini banyak pustaka JavaScript yang terkenal menyediakan metode mereka sendiri untuk mengulangi koleksi, yaitu lebih dari array , objek , dan objek seperti array . Metode-metode ini nyaman digunakan dan sepenuhnya kompatibel dengan browser apa pun.

  1. Jika Anda bekerja dengan jQuery , Anda dapat menggunakan jQuery.each()metode. Ini dapat digunakan untuk beralih mulus pada objek dan array:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. Di Underscore.js Anda dapat menemukan metode _.each(), yang beralih pada daftar elemen, menghasilkan masing-masing pada fungsi yang disediakan (perhatikan urutan argumen dalam fungsi iteratee !):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash menyediakan beberapa metode untuk mengulangi properti objek. Dasar _.forEach()(atau alias _.each()) berguna untuk perulangan melalui kedua objek dan array, namun (!) Objek dengan lengthproperti diperlakukan seperti array, dan untuk menghindari perilaku ini disarankan untuk menggunakan _.forIn()dan _.forOwn()metode (ini juga memiliki valueargumen yang datang terlebih dahulu):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });

    _.forIn()iterate atas properti enumerable milik sendiri dan diwarisi objek, sementara _.forOwn()iterates hanya atas properti sendiri objek (pada dasarnya memeriksa terhadap hasOwnPropertyfungsi). Untuk objek sederhana dan objek literal, salah satu dari metode ini akan berfungsi dengan baik.

Secara umum semua metode yang dijelaskan memiliki perilaku yang sama dengan objek yang disediakan. Selain menggunakan for..inloop asli biasanya akan lebih cepat daripada abstraksi apa pun, seperti jQuery.each(), metode ini jauh lebih mudah digunakan, memerlukan lebih sedikit pengkodean dan memberikan penanganan kesalahan yang lebih baik.

Penglihatan
sumber
4
Untuk sampai ke nilai: $ .each (obj, function (key, value) {console.log (value.title);});
Ravi Ram
2
Hanya lucu bagaimana garis bawah dan jquery mengubah parameter :)
ppasler
52

Dalam ECMAScript 5 Anda memiliki pendekatan baru dalam bidang iterasi literal - Object.keys

Informasi lebih lanjut dapat Anda lihat di MDN

Pilihan saya di bawah ini sebagai solusi yang lebih cepat di versi browser saat ini (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Anda dapat membandingkan kinerja dari pendekatan ini dengan implementasi berbeda di jsperf.com :

Dukungan browser dapat Anda lihat di tabel compat Kangax

Untuk browser lama, Anda memiliki polyfill yang sederhana dan lengkap

UPD:

perbandingan kinerja untuk semua kasus paling populer dalam pertanyaan ini pada perfjs.info:

objek iterasi literal

Pencroff
sumber
Memang, saya hanya ingin memposting metode ini. Tapi Anda mengalahkan saya untuk itu :(
Jamie Hutber
50

Kata pengantar:

  • Properti objek dapat menjadi milik sendiri (properti berada pada objek itu sendiri) atau diwariskan (bukan pada objek itu sendiri, pada salah satu prototipe).
  • Properti objek dapat enumerable atau non-enumerable . Properti non-enumerable ditinggalkan dari banyak enumerasi / array properti.
  • Nama properti dapat berupa string atau Simbol. Properti yang namanya Simbol ditinggalkan dari banyak enumerasi / array properti.

Di sini pada tahun 2018, opsi Anda untuk perulangan melalui properti objek adalah (beberapa contoh ikuti daftar):

  1. for-in[ MDN , spec ] - Struktur lingkaran yang loop melalui nama-nama properti enumerable objek , termasuk yang diwarisi, yang namanya adalah string
  2. Object.keys[ MDN , spec ] - Fungsi yang menyediakan array nama-nama properti milik sendiri , enumerable properties yang namanya string.
  3. Object.values[ MDN , spesifikasi ] - Sebuah fungsi yang menyediakan sebuah array dari nilai-nilai dari obyek sendiri , enumerable properti.
  4. Object.entries[ MDN , spec ] - Fungsi yang menyediakan larik nama dan nilai properti sendiri , properti yang dapat dihitung (setiap entri dalam larik adalah [name, value]larik).
  5. Object.getOwnPropertyNames[ MDN , spec ] - Suatu fungsi yang menyediakan larik nama-nama properti objek sendiri (bahkan yang non-enumerable) yang namanya adalah string.
  6. Object.getOwnPropertySymbols[ MDN , spec ] - Suatu fungsi yang menyediakan larik nama-nama properti objek sendiri (bahkan yang non-enumerable) yang namanya Simbol.
  7. Reflect.ownKeys[ MDN , spec ] - Fungsi yang menyediakan array nama-nama objek itu sendiri properti (bahkan yang non-enumerable), baik nama-nama itu string atau Simbol.
  8. Jika Anda ingin semua properti obyek, termasuk yang diwariskan non-enumerable, Anda perlu menggunakan loop dan Object.getPrototypeOf[ MDN , spesifikasi ] dan penggunaan Object.getOwnPropertyNames, Object.getOwnPropertySymbolsatau Reflect.ownKeyspada setiap objek dalam rantai prototipe (misalnya di bagian bawah jawaban ini).

Dengan mereka semua kecuali for-in, Anda akan menggunakan beberapa jenis perulangan membangun pada array ( for, for-of, forEach, dll).

Contoh:

for-in:

Object.keys (dengan for-ofloop, tetapi Anda dapat menggunakan konstruk looping apa pun) :

Object.values:

Object.entries:

Object.getOwnPropertyNames:

Object.getOwnPropertySymbols:

Reflect.ownKeys:

Semua properti , termasuk yang diwarisi non-enumerable:

TJ Crowder
sumber
Tambahan bagus properti objek enumerable / non-enumberable.
serraosays
49

Anda bisa mengulanginya seperti:

for (var key in p) {
  alert(p[key]);
}

Perhatikan bahwa keytidak akan mengambil nilai properti, itu hanya nilai indeks.

Bryan
sumber
13
Ini diulangi dan bahkan tidak sepenuhnya benar. Anda perlu memeriksa hasOwnProperty untuk membuat ini berfungsi dengan baik
Vatsal
4
Saya awalnya downvoted ini berdasarkan komentar di atas sampai saya menyadari bahwa jawaban ini datang lebih dulu, oleh karena itu tidak "diulang". Ini mungkin tidak lengkap tetapi berfungsi dengan baik untuk banyak kasus.
billynoah
27

Karena es2015 semakin populer, saya memposting jawaban ini yang mencakup penggunaan generator dan iterator untuk secara lancar beralih melalui [key, value]pasangan. Karena dimungkinkan dalam bahasa lain misalnya Ruby.

Oke, ini kode:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Semua informasi tentang bagaimana Anda bisa melakukan iterator dan generator yang dapat Anda temukan di halaman pengembang Mozilla.

Semoga itu membantu seseorang.

EDIT:

ES2017 akan termasuk Object.entriesyang akan membuat iterasi [key, value]pasangan pada objek bahkan lebih mudah. Sekarang diketahui bahwa itu akan menjadi bagian dari standar menurut ts39 informasi tahap .

Saya pikir sudah waktunya untuk memperbarui jawaban saya untuk membuatnya menjadi lebih segar daripada sekarang.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Anda dapat menemukan lebih banyak tentang penggunaan di halaman MDN

FieryCod
sumber
Ini terlihat sangat berlebihan bagi saya. Apakah Anda menambahkannya ke setiap objek di sistem Anda? Saya pikir tujuan menyediakan iterator adalah agar Anda dapat melakukan `for (const [k, v] myObject) '. Sepertinya kode tambahan memberikan sedikit nilai tambah.
Dean Radcliffe
22
for(key in p) {
  alert( p[key] );
}

Catatan: Anda bisa melakukan ini di atas array, tetapi Anda juga akan mengulanginya di atas lengthdan properti lainnya.

Richard Levasseur
sumber
4
Saat menggunakan for for seperti itu, keyhanya akan mengambil nilai indeks, jadi itu hanya akan mengingatkan 0, 1, 2, dll ... Anda perlu mengakses p [kunci].
Bryan
1
Ini adalah metode paling lambat dari pengulangan array dalam JavaScript. Anda dapat memeriksa ini di komputer Anda - Cara terbaik untuk mengulangi lebih dari Array dalam JavaScript
Pencroff
5
@Pencroff: masalahnya adalah pertanyaannya bukan tentang perulangan melalui array ...;)
Sk8erPeter
Ini adalah sesuatu yang saya tidak mengerti tentang stackoverflow. Richard memberikan jawaban yang benar, dan dia yang pertama memberikan jawaban itu, tetapi dia tidak mendapatkan +1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }muncul "p1" dan "p2" di peringatan, jadi apa yang salah tentang itu ???
Sebastian
5
Saya pikir perbedaan utama adalah kualitas: jawaban yang lain tidak hanya mengatakan bagaimana, tetapi juga memberi tahu peringatan (misalnya, prototipe) dan bagaimana menangani peringatan tersebut. IMHO, jawaban - jawaban lain lebih baik dari saya :).
Richard Levasseur
20

Setelah melihat semua jawaban di sini, hasOwnProperty tidak diperlukan untuk penggunaan saya sendiri karena objek json saya bersih; benar-benar tidak masuk akal dalam menambahkan pemrosesan javascript tambahan. Ini yang saya gunakan:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}
Francis Lewis
sumber
18
Apakah objek JSON bersih atau tidak tidak relevan. Jika suatu saat beberapa kode mengaktifkan properti Object.prototype, maka itu akan disebutkan oleh for..in. Jika Anda yakin tidak menggunakan perpustakaan yang melakukan itu, maka Anda tidak perlu menelepon hasOwnProperty.
G-Wiz
4
Ini dapat sepenuhnya bersih jika dibuat denganObject.create(null)
Juan Mendes
20

via prototipe dengan forEach () yang harus melewati properti rantai prototipe :

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3
Strider
sumber
2
Hati-hati dengan prototipe: obj = { print: 1, each: 2, word: 3 }menghasilkan TypeError: number is not a function. Menggunakan forEachuntuk mencocokkan Arrayfungsi yang serupa dapat mengurangi risiko.
David Harkness
18

Sangat menarik bahwa orang-orang dalam jawaban ini menyentuh keduanya Object.keys()dan for...oftetapi tidak pernah menggabungkannya:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Anda tidak bisa hanya for...ofsebuah Objectkarena itu bukan iterator, dan for...indexatau .forEach()ing Object.keys()jelek / tidak efisien.
Saya senang kebanyakan orang menahan diri dari for...in(dengan atau tanpa memeriksa .hasOwnProperty()) karena itu juga agak berantakan, jadi selain jawaban saya di atas, saya di sini untuk mengatakan ...


Anda dapat membuat asosiasi objek biasa beralih! Berperilaku seperti Mapdengan penggunaan langsung dari mewahfor...of
DEMO bekerja di Chrome dan FF (saya berasumsi hanya ES6)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Selama Anda memasukkan shim saya di bawah ini:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Tanpa harus membuat objek Peta nyata yang tidak memiliki gula sintaksis yang bagus.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

Faktanya, dengan shim ini, jika Anda masih ingin memanfaatkan fungsionalitas Map lainnya (tanpa mengurangi semuanya) tetapi masih ingin menggunakan notasi objek yang rapi, karena objek sekarang dapat diubah, Anda sekarang dapat membuat Peta darinya!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Bagi mereka yang tidak suka shim, atau mengacaukan prototypesecara umum, jangan ragu untuk membuat fungsi di jendela, menyebutnya seperti getObjIterator()itu;

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

Sekarang Anda bisa menyebutnya sebagai fungsi biasa, tidak ada yang terpengaruh

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

atau

for (let pair of getObjIterator(ordinaryObject))

Tidak ada alasan mengapa itu tidak berhasil.

Selamat datang di masa depan.

Hashbrown
sumber
1
Kasus di titik . Selama orang-orang gulir ke bawah dan merasa terbantu, itu yang terpenting. Biasanya saya mencoba melakukan sesuatu, tidak menyukai hal-hal yang saya lihat online, akhirnya mencari tahu, lalu saya kembali untuk berbagi. Ini dokumen yang bagus, saya sudah menemukan jawaban sendiri sebelum googling hal-hal yang saya benar-benar lupa!
Hashbrown
@HelpMeStackOverflowMyOnlyHope Secara pribadi saya tidak suka memodifikasi prototipe objek yang tidak saya definisikan sendiri.
Janus Troelsen
@ JanusTroelsen, apakah Anda bahkan membaca seluruh jawaban? For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
Hashbrown
Perhatikan bahwa teknik ini tidak bekerja pada objek biasa, tetapi tetap berguna.
noɥʇʎԀʎzɐɹƆ
itu berfungsi untuk objek polos, itu benar-benar seluruh titik (serta nama variabel seperti ordinaryObjectuntuk penekanan bahwa sihir masih berfungsi untuk jenis-jenis itu). Apakah Anda memeriksa demo; apa yang tidak berhasil untuk Anda, @ noɥʇʎԀʎzɐɹƆ? (PS gambar profil SE Anda adalah bos)
Hashbrown
13

Object.keys (obj): Array

mengambil semua kunci bernilai string dari semua properti enumerable sendiri (non-warisan).

Jadi itu memberikan daftar kunci yang sama seperti yang Anda maksudkan dengan menguji setiap kunci objek dengan hasOwnProperty. Anda tidak memerlukan operasi tes ekstra daripada dan Object.keys( obj ).forEach(function( key ){})seharusnya lebih cepat. Mari kita buktikan:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

Di Firefox saya, saya memiliki hasil sebagai berikut

  • Pendekatan Object.keys mengambil 40,21101451665163 milidetik.
  • untuk ... dalam / hasOwnProperty pendekatan mengambil 98,26163508463651 milidetik.

PS. di Chrome perbedaannya lebih besar http://codepen.io/dsheiko/pen/JdrqXa

PS2: Dalam ES6 (EcmaScript 2015) Anda dapat beralih objek yang lebih baik iterable:

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});

Dmitry Sheiko
sumber
jika Anda tidak ingin melepaskan notasi {}, Anda masih dapat menggunakan of tanpa membuat Maps
Hashbrown
13

Berikut adalah metode lain untuk beralih melalui suatu objek.

   var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};


Object.keys(p).forEach(key => { console.log(key, p[key]) })

Harsh Patel
sumber
3
Ini cukup keren, namun untuk objek besar, formetode ini mungkin lebih performan.
Rolf
13

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>

ParaMeterz
sumber
12

Anda juga dapat menggunakan Object.keys () dan beralih di atas kunci objek seperti di bawah ini untuk mendapatkan nilai:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});

Onera
sumber
Anda menghemat waktu saya, Terima kasih
Swap-IOS-Android
Senang tahu :)
Onera
8

Hanya kode JavaScript tanpa ketergantungan:

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]

for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}
mohamed-ibrahim
sumber
8

The Object.keys()Metode mengembalikan array properti enumerable objek diberikan sendiri. Baca lebih lanjut di sini

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))

George Bailey
sumber
8

Performa

Hari ini 2020.03.06 Saya melakukan pengujian terhadap solusi yang dipilih pada Chrome v80.0, Safari v13.0.5 dan Firefox 73.0.1 pada MacOs High Sierra v10.13.6

Kesimpulan

  • solusi berdasarkan for-in (A, B) cepat (atau tercepat) untuk semua browser untuk objek besar dan kecil
  • heran for-ofsolusi (H) adalah cepat pada chrome untuk benda kecil dan besar
  • solusi berdasarkan indeks eksplisit i (J, K) cukup cepat di semua browser untuk objek kecil (untuk firefox juga cepat untuk ojbects besar tetapi sedang cepat di browser lain)
  • solusi berdasarkan iterator (D, E) paling lambat dan tidak direkomendasikan
  • solusi C lambat untuk benda besar dan sedang-lambat untuk benda kecil

masukkan deskripsi gambar di sini

Detail

Tes kinerja dilakukan untuk

  • benda kecil - dengan 3 bidang - Anda dapat melakukan tes pada mesin Anda DI SINI
  • objek 'besar' - dengan 1000 bidang - Anda dapat melakukan tes pada mesin Anda DI SINI

Cuplikan di bawah ini menyajikan solusi yang digunakan

Dan di sini adalah hasil untuk benda kecil di chrome

masukkan deskripsi gambar di sini

Kamil Kiełczewski
sumber
7

Anda dapat menambahkan fungsi forEach sederhana ke semua objek, sehingga Anda dapat secara otomatis mengulangi objek apa pun:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

Bagi orang-orang yang tidak menyukai " untuk ... dalam " metode:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

Sekarang, Anda dapat menelepon sederhana:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

Jika Anda tidak ingin mendapatkan konflik dengan Metode-metode lainnya untuk setiap metode, Anda dapat menamainya dengan nama unik Anda.

Biber
sumber
3
Memodifikasi prototipe objek bawaan (seperti Object) umumnya dianggap sebagai pola anti karena dapat dengan mudah menyebabkan konflik dengan kode lain. Jadi luka tidak merekomendasikan melakukannya dengan cara ini.
Moritz
6

Loop bisa sangat menarik saat menggunakan JavaScript murni. Tampaknya hanya ECMA6 (Spesifikasi JavaScript Baru 2015) yang dapat mengendalikan loop. Sayangnya saat saya menulis ini, baik Browser dan lingkungan pengembangan terintegrasi (IDE) masih berjuang untuk mendukung sepenuhnya lonceng dan peluit baru.

Sekilas di sini adalah seperti apa bentuk lingkaran objek JavaScript sebelum ECMA6:

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

Juga, saya tahu ini di luar ruang lingkup dengan pertanyaan ini tetapi pada tahun 2011, ECMAScript 5.1 menambahkan forEachmetode hanya untuk Array yang pada dasarnya menciptakan cara baru yang ditingkatkan untuk loop melalui array sementara masih meninggalkan objek yang tidak dapat diubah dengan verbose yang lama dan forloop yang membingungkan . Tetapi bagian yang aneh adalah bahwa forEachmetode baru ini tidak mendukung breakyang menyebabkan semua jenis masalah lainnya.

Pada dasarnya di 2011, tidak ada cara yang benar-benar solid untuk mengulang JavaScript selain dari apa yang banyak perpustakaan populer (jQuery, Underscore, dll.) Memutuskan untuk menerapkan kembali.

Pada 2015, kami sekarang memiliki cara yang lebih baik di luar kotak untuk mengulang (dan memecah) semua jenis objek (termasuk Array dan Strings). Berikut adalah tampilan loop dalam JavaScript ketika rekomendasi menjadi arus utama:

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

Perhatikan bahwa sebagian besar browser tidak akan mendukung kode di atas pada 18 Juni 2016. Bahkan di Chrome Anda harus mengaktifkan tanda khusus ini agar dapat berfungsi: chrome://flags/#enable-javascript-harmony

Sampai ini menjadi standar baru, metode lama masih dapat digunakan tetapi ada juga alternatif di perpustakaan populer atau bahkan alternatif ringan bagi mereka yang tidak menggunakan perpustakaan ini.

Nicolas Bouvrette
sumber
Bisakah Anda menyediakan biola untuk pekerjaan ini? Ini usahaku. jsfiddle.net/abalter/sceeb211
abalter
@abalter Maaf saya menyadari saya salah ketik dalam kode saya. Saya memperbaikinya dan memperbarui JsFiddle Anda di sini: jsfiddle.net/sceeb211/2
Nicolas Bouvrette
Saya di chrome dan mendapatkan Uncaught TypeError: Object.entries is not a function. Apakah ini belum diterapkan di chrome?
Abalter
@abalter Ini. Pastikan Anda memiliki Chrome versi 51 dan bahwa Anda telah mengaktifkan bendera seperti yang dijelaskan dalam edit saya dan komentar Jsfiddle. Anda dapat memeriksa detailnya di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette
Maaf saya melewatkan itu tentang bendera. Saya melihat itu belum sepenuhnya diimplementasikan.
Abalter
5

Dalam ES6 kami memiliki simbol terkenal untuk mengekspos beberapa metode internal sebelumnya, Anda dapat menggunakannya untuk menentukan bagaimana iterator bekerja untuk objek ini:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

ini akan memberikan hasil yang sama seperti menggunakan for ... di es6 loop.

for(var key in p) {
    console.log(key);
}

Tetapi penting untuk mengetahui kemampuan yang sekarang Anda miliki menggunakan es6!

Bamieh
sumber
1
Iterator objek kustom memanggil iterator larik bawaan array yang dihasilkan oleh Object.keys()dan dialokasikan dalam memori ... Keren!
Aduh
5

Saya akan melakukan ini daripada memeriksa obj.hasOwnerPropertydalam setiap for ... inloop.

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}
Lewis
sumber
5

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}

senthil
sumber
json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }
Marek Bernád
5

Menggunakan for-ofonObject.keys()

Suka:

let object = {
   "key1": "value1"
   "key2": "value2"
   "key3": "value3"
};

for (var key of Object.keys(p)) {
   console.log(key + " : " + object[key])
}
Nicolas Cabanas
sumber
4

Jika Anda ingin mengulangi juga properti yang tidak dapat dihitung , Anda dapat menggunakan Object.getOwnPropertyNames(obj)untuk mengembalikan array semua properti (yang dapat dihitung atau tidak) yang ditemukan langsung pada objek yang diberikan.

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

obj.foo = 1; // enumerable property

Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});

Dheeraj Vepakomma
sumber
2
Ini luar biasa, terima kasih telah mengirimkan jawaban ini. Saya perlu mengintrospeksi Errorobjek dan tidak bisa mendapatkan properti dalam satu lingkaran atau _.forIn(err)panggilan. Menggunakan Object.getOwnPropertyNames(err)memungkinkan saya untuk mengakses semua bagian Erroryang tidak bisa saya dapatkan sebelumnya. Terima kasih!
Pierce
4

Jika ada yang perlu mengulang melalui arrayObjects dengan kondisi :

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}

Tadas V.
sumber
4

Mempertimbangkan ES6 Saya ingin menambahkan sendok gula saya sendiri dan memberikan satu pendekatan lagi untuk beralih pada sifat-sifat objek.

Karena objek JS biasa tidak dapat diubah hanya di luar kotak, kami tidak dapat menggunakan for..ofloop untuk mengulangi kontennya. Tapi tidak ada yang bisa menghentikan kita untuk membuatnya lebih baik .

Mari kita punya bookobjek.

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

Karena kita sudah membuatnya kita bisa menggunakannya dengan cara ini:

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

Atau jika Anda mengetahui kekuatan generator ES6 , maka Anda tentu dapat membuat kode di atas jauh lebih pendek.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

Tentu, Anda dapat menerapkan perilaku seperti itu untuk semua objek dengan membuatnya tingkat di Objectatas prototype.

Object.prototype[Symbol.iterator] = function() {...}

Juga, objek yang mematuhi protokol iterable dapat digunakan dengan operator penyebaran fitur ES2015 baru sehingga kita dapat membaca nilai properti objek sebagai array.

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

Atau Anda dapat menggunakan destructuring tugas:

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

Anda dapat memeriksa JSFiddle dengan semua kode yang saya berikan di atas.

Artyom Pranovich
sumber
Saya menemukan kode akan menghasilkan nilai tetapi tanpa kunci. Apakah mungkin untuk mengembalikan nilai dengan kunci?
Pika
Ya kamu bisa. Cukup kembalikan "hasilkan [kunci, objek [kunci]];" dari fungsi generator Anda dan kemudian gunakan seperti berikut "untuk (biarkan [kunci, nilai] dari {}) {}"
Artyom Pranovich
4

karena ES06 Anda bisa mendapatkan nilai-nilai objek dengan array

let arrValues = Object.values( yourObject) ;

mengembalikan array nilai objek dan tidak mengekstrak nilai dari Prototipe !!

Object.values ​​MDN DOCS ()

dan untuk kunci (sudah ada jawab sebelum saya di sini)

let arrKeys   = Object.keys(yourObject);
yehonatan yehezkel
sumber
Jawabannya meminta solusi yang mengembalikan kunci dan nilai.
Sean Lindo
4

Dalam skrip ES terbaru, Anda dapat melakukan sesuatu seperti ini:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}

Ankit
sumber