Bir JavaScript nesnesini nasıl döngüleyebilir veya numaralandırabilirim?


2878

Aşağıdaki gibi bir JavaScript nesnesi var:

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

Şimdi tüm döngü isteyen punsurların ( p1, p2, p3...) Ve kendi anahtarlarını ve değerlerini almak. Bunu nasıl yapabilirim?

Gerekirse JavaScript nesnesini değiştirebilirim. Nihai hedefim bazı anahtar değer çiftleri arasında döngü yapmak ve mümkünse kullanmaktan kaçınmak istiyorum eval.


9
Nesne değişmez değerleri ve JSON'un karışmasını önlemek için JSON'u JavaScript (nesne) olarak değiştirdim.
Felix Kling

Yanıtlar:


4366

for-inDöngüyü başkaları tarafından gösterildiği gibi kullanabilirsiniz . Ancak, aldığınız anahtarın bir nesnenin gerçek bir özelliği olduğundan ve prototipten gelmediğinden de emin olmalısınız.

Parçacık İşte:

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

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

Object.keys () alternatifiyle birlikte:

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

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

for-ofBunun yerine kullanıldığına dikkat edin, kullanılmazsa for-inadlandırılmış özelliklerde tanımsız olarak döndürülür Object.keys()ve tüm prototip zinciri özellikleri olmadan yalnızca nesnenin kendi özelliklerinin kullanılmasını sağlar.

Yeni Object.entries()yöntemi kullanarak :

Not: Bu yöntem Internet Explorer tarafından yerel olarak desteklenmez. Eski tarayıcılar için bir Çoklu Dolgu kullanmayı düşünebilirsiniz.

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

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

34
Uyarı satırını sadece netlik için değiştirmenizi alert(key + " -> " + JSON.stringify(p[key]));
öneririm

80
HasOwnProperty'ye olan ihtiyacı açıklayabilir misiniz? Prototip ile ne demek istiyorsun?
kamacı

331
Javascript'te her nesnede, meta bilgileri olan bir grup yerleşik anahtar / değer çifti bulunur. Bir nesnenin tüm anahtar / değer çiftleri arasında geçiş yaptığınızda, bunlar arasında da döngü gerçekleştirirsiniz. hasOwnPropery () bunları filtreler.
danieltalsky

57
Aslında, ... in için kullanımdan kaldırılamaz. Her biri için ... in . Ama arkeologlar terimini çok seviyorum ... Bunu kullanmaya başlamak zorunda kalacağım.
Ben Y

17
javascript'teki her nesnenin (aslında bir anahtar / değer çifti) __proto__veya adlı bir özelliğe sahiptir prototype. Bu özelliğin üst nesnesine bir başvurusu var. Bir nesne, özelliği üst öğesinden otomatik olarak devralır. Bu, hasOwnPropertyana nesnelerle değil nesnelerin kendi mülkleriyle ilgilendiğimizi gösteren kullanım nedenidir .
Zubair Alam

1104

ECMAScript'e 5 altında, birleştirebilir Object.keys()ve Array.prototype.forEach():

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

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

ECMAScript 6 şunları ekler for...of:

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

ECMAScript 8 Object.entries(), orijinal nesnedeki her bir değere bakmak zorunda kalmadan ekler :

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

Birleştirebilir for...of, yok edebilir ve Object.entries:

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

Her ikisi de Object.keys()ve Object.entries()özellikleri for...indöngü ile aynı sırayla yineler ancak prototip zincirini yok sayar . Yalnızca nesnenin kendi numaralandırılabilir özellikleri yinelenir.


21
Standart neden sağlamadı Object.forEach(obj, function (value, key) {...})? :( Kesinlikle obj.forEach(function...)daha kısa ve tamamlayıcı Array.prototype.forEacholurdu, ama bu nesnelerin kendi forEachmülklerini tanımlaması riskine yol açacaktır.Onun Object.keys, nesnenin anahtarlarını değiştiren geri aramaya karşı muhafızlar olduğunu düşünüyorum .
David Harkness

7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness

7
@DavidHarkness ES2017'de Object.entries var. Orada aşağıdakileri yapabilirsiniz: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([anahtar, değer], her iki öğeye doğrudan erişmek için dizi yıkıcıdır. Ve parametreleri ek
ebeveynlerde sarmanız gerekir

nasıl indexjson anahtar alabilirim ? Veya gerekirse ayrı bir sayaç kullanmalıyım?
Saravanabalagi Ramachandran

3
for...ofES6 standardıdır, ES2016 değil.
Rax Weber

342

Sen kullanmak zorunda for-in döngüsünü

Ancak bu tür bir döngüyü kullanırken çok dikkatli olun, çünkü bu , prototip zinciri boyunca tüm özellikleri döngüleyecektir .

Bu nedenle, for-in döngülerini kullanırken, hasOwnPropertyyinelemedeki geçerli özelliğin gerçekten kontrol ettiğiniz nesnenin bir özelliği olup olmadığını belirlemek için her zaman yöntemi kullanın:

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
}

31
Bu, levik'in çözümünden daha iyidir, çünkü ana mantığın iki yerine sadece bir iç içe döngü olmasına izin verir; kodun okunmasını kolaylaştırır. Rağmen devam parantez etrafında parantez; onlar gereksiz.
SystemicPlural

52
Şahsen kaldırmazdım { }çünkü ifonlarsız bir şeyin neyin parçası olduğunu ifve neyin olmadığını biraz belirsizleştirir . Ama sanırım bu sadece bir fikir meselesi :)
pimvdb

34
Evet, { }daha sonra ifkapsama bir şey eklemesi gerekiyorsa, karışıklığı önlemek için esas olarak saklamayı tercih ederim .
Andreas Grech

8
Önceki yorumumu okurken, doğru terimleri kullanmadığımı fark ettim, çünkü “kapsam” dediğimde; ancak JavaScript'in yalnızca işlev kapsamı olduğunu unutmayın. Demek istediğim aslında "if block" idi.
Andreas Grech

1
eomeroff, eğer gerçekten bu konuda endişeleriniz varsa, her zaman böyle bir şey yapabilirsiniz: Object.prototype.hasOwnProperty.call(p, prop) Bununla birlikte, bu da Object.prototype'e karşı manipülasyonlara karşı koruyamaz ...
jordancpaul

252

Nesneler arasında döngü oluşturmak için alternatif yöntemlerden bahsetmezsek soru tamamlanmayacaktır.

Günümüzde iyi bilinen birçok JavaScript kütüphanesi, koleksiyonlar, yani diziler , nesneler ve dizi benzeri nesneler üzerinde yineleme yapmak için kendi yöntemlerini sağlar . Bu yöntemlerin kullanımı uygundur ve tüm tarayıcılarla tamamen uyumludur.

  1. JQuery ile çalışıyorsanız , jQuery.each()yöntemi kullanabilirsiniz . Hem nesneler hem de diziler üzerinde sorunsuz bir şekilde yineleme yapmak için kullanılabilir:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. In Underscore.js Eğer yöntemini bulabilirsiniz _.each()bir sağlanan işleve sırayla her verimli, elemanların listesi üzerinde dolaşır, (argümanlar sırasına ödeme dikkat iteratee fonksiyonu!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash , nesne özellikleri üzerinde yineleme yapmak için çeşitli yöntemler sunar. Temel _.forEach()(veya diğer adı _.each()) hem nesneler hem de diziler arasında döngü yapmak için kullanışlıdır, ancak (!) lengthÖzelliğine sahip nesnelere diziler gibi davranılır ve bu davranışı önlemek için _.forIn()ve _.forOwn()yöntemlerin kullanılması önerilir (bunlar da önce valuegelen argümanlara sahiptir ):

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

    _.forIn()üzerinde dolaşır kendi ve kalıtsal bir nesnenin enumerable özellikleri ise _.forOwn()dolaşır sadece üzerinde kendi bir nesnenin özellikleri (temelde karşı kontrol hasOwnPropertyfonksiyonu). Basit nesneler ve nesne değişmez değerleri için bu yöntemlerden herhangi biri sorunsuz çalışır.

Genellikle açıklanan tüm yöntemler, sağlanan nesnelerle aynı davranışa sahiptir. Doğal kullanmanın yanı sıra for..ingenellikle olacak döngü daha hızlı gibi herhangi bir soyut daha jQuery.each(), bu yöntemler, kullanıcı için önemli ölçüde daha kolay olan daha az kodlama gerektirir ve daha iyi hata giderme sağlar.


4
Değere ulaşmak için: $ .each (obj, function (anahtar, değer) {console.log (value.title);});
Ravi Ram

2
Sadece komik alt çizgi ve jquery parametreleri değiştirdi :)
ppasler

52

ECMAScript 5'te gerçekte yineleme alanlarında yeni bir yaklaşım var - Object.keys

MDN hakkında daha fazla bilgi görebilirsiniz

Seçimim, tarayıcıların mevcut sürümlerinde (Chrome30, IE10, FF25) daha hızlı bir çözüm olarak aşağıda

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

Bu yaklaşımın performansını jsperf.com'daki farklı uygulamalarla karşılaştırabilirsiniz :

Kangax'ın uyumluluk tablosunda görebileceğiniz tarayıcı desteği

Eski tarayıcı için basit ve tam çoklu dolgunuz var

UPD:

Bu sorudaki en popüler tüm durumlar için performans karşılaştırması perfjs.info:

nesne değişmez yinelemesi


Gerçekten, sadece bu yöntemi göndermek istedim. Ama beni
dövüyorsun

50

Önsöz:

  • Nesne özellikleri kendi olabilir (özellik nesnenin kendisindedir) veya miras alınabilir (nesnenin kendisinde değil, prototiplerinden birinde).
  • Nesne özellikleri numaralandırılabilir veya numaralandırılamaz . Numaralandırılamayan özellikler, birçok özellik numaralandırma / dizisinin dışında bırakılır.
  • Özellik adları dize veya Sembol olabilir. İsimleri Sembol olan özellikler, birçok özellik numaralandırmasından / dizisinden çıkarılır.

Burada 2018'de, bir nesnenin özellikleri arasında döngü yapma seçenekleriniz (bazı örnekler listeyi takip eder):

  1. for-in[ MDN , spec ] - Devralınan olanlar da dahil olmak üzere adları dizeler olan bir nesnenin numaralandırılabilir özelliklerinin adlarında dolaşan bir döngü yapısı
  2. Object.keys[ MDN , spek ] - Bir nesnenin isimlerini içeren bir dizi sağlayan bir fonksiyonu , kendi , numaralandırılabilir isimleri şeritleri olan özellikleri.
  3. Object.values[ MDN , spek ] - bir fonksiyon bir dizi sağlayan değerler , bir nesnenin bir kendi , numaralandırılabilir özellikleri.
  4. Object.entries[ MDN , spek ] - adlarının dizisini sağlayan bir fonksiyonu ve bir nesnenin değerlerine ait , numaralandırılabilir özellikleri (dizideki her bir giriş a, [name, value]dizi).
  5. Object.getOwnPropertyNames[ MDN , spec ] - Nesnelerin adları dizeleri olan kendi özelliklerinin (numaralandırılamayanlar için bile) bir dizi dizisini sağlayan bir işlev .
  6. Object.getOwnPropertySymbols[ MDN , spec ] - Bir nesnenin , adları Sembol olan kendi özelliklerinin (numaralandırılamayanlar için bile) adlarını içeren bir işlev .
  7. Reflect.ownKeys[ MDN , spec ] - Bir nesnenin kendi özelliklerinin (numaralandırılamayanlar için bile olsa) adlarını içeren bir dizi sağlayan bu işlev , ister dize ister Sembol olsun.
  8. İsterseniz tüm olmayan enumerable kalıtsal olanlar dahil bir nesnenin özelliklerinin, bir döngü ve kullanmak gerekir Object.getPrototypeOf[ MDN , Spec ] ve kullanımı Object.getOwnPropertyNames, Object.getOwnPropertySymbolsya da Reflect.ownKeys(bu cevabın altındaki örnek) Her prototip zincirinde nesne üzerinde.

Hepsi hariç sayesinde for-in, siz (dizi yapısını döngü çeşit kullanmayı tercih for, for-of, forEachvb.)

Örnekler:

for-in:

Object.keys (bir for-ofdöngü ile, ancak herhangi bir döngü yapısını kullanabilirsiniz) :

Object.values:

Object.entries:

Object.getOwnPropertyNames:

Object.getOwnPropertySymbols:

Reflect.ownKeys:

Miras alınmayan numaralandırılmamış olanlar dahil tüm özellikler :


Numaralandırılabilir / numaralandırılamaz nesne özelliklerinin güzel bir şekilde eklenmesi.
serraosays

49

Sadece bunun gibi tekrarlayabilirsiniz:

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

keyÖzelliğin değerini almayacağını unutmayın , bu sadece bir dizin değeridir.


13
Bu tekrarlanır ve tamamen doğru değildir. Bu düzgün çalışması için hasOwnProperty bir kontrol olması gerekir
Vatsal

4
Bu cevabın ilk geldiğini fark edene kadar başlangıçta yukarıdaki yoruma dayanarak bunu düşürdüm, bu nedenle "tekrarlanmadı". Muhtemelen eksiktir, ancak birçok durumda iyi çalışır.
billynoah

27

Es2015 gittikçe daha popüler hale geldiğinden, [key, value]çiftler arasında sorunsuz bir şekilde yineleme yapmak için jeneratör ve yineleyici kullanımını içeren bu cevabı gönderiyorum . Diğer dillerde mümkün olduğu gibi, örneğin Ruby.

Tamam burada bir kod:

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}`);
}

Nasıl bir yineleyici ve jeneratör yapabilirsiniz hakkında tüm bilgiler geliştirici Mozilla sayfasında bulabilirsiniz.

Umarım birine yardımcı olmuştur.

DÜZENLE:

ES2017, nesnelerdeki çiftler Object.entriesüzerinde yinelemeyi [key, value]daha da kolaylaştıracak. Artık ts39 sahne bilgisine göre bir standardın parçası olacağı bilinmektedir .

Sanırım cevabımı şimdi olduğundan daha taze hale getirmek için güncelleme zamanı.

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}`);
}

Kullanım hakkında daha fazla bilgiyi MDN sayfasında bulabilirsiniz


Bu tamamen gereksiz / gereksiz görünüyor. Sisteminizdeki her nesneye ekler misiniz? Bir yineleyici sağlama noktasının `` myObject için const [k, v] '' yapabileceğinizi düşündüm. Çok az ek değer sağlayan ekstra kod gibi görünüyor.
Dean Radcliffe

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

Not: Bunu diziler üzerinden yapabilirsiniz, ancak lengthdiğer özellikleri de yineleyeceksiniz .


4
Böyle bir for döngüsü kullanırken key, sadece bir dizin değeri alır, böylece 0, 1, 2, vb. Uyarır. P [key] öğesine erişmeniz gerekir.
Bryan

1
JavaScript'te dizi yinelemenin en yavaş yöntemidir. Bilgisayarınızda bunu kontrol edebilirsiniz - JavaScript Diziler üzerinde yineleme için en iyi yol
Pencroff

5
@Pencroff: sorun şu ki, diziler arasında döngü
yapmakla

Bu yığın akışında anlamadığım bir şey. Richard doğru cevabı verdi ve bu cevabı veren ilk kişi oydu, ancak +1 alamadı mı? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }uyarılar "p1" ve "p2" haşhaş, bu yüzden bu konuda yanlış ne ???
Sebastian

5
Temel farkın kalite olduğunu düşünüyorum: diğer cevaplar sadece nasıl olduğunu değil, aynı zamanda uyarıları (örneğin, prototip) ve bu uyarılarla nasıl başa çıkılacağını da anlatıyor. IMHO, bu diğer cevaplar vardır :) iyi benim daha.
Richard Levasseur

20

Buradaki tüm cevapları inceledikten sonra, json nesnem temiz olduğu için kendi kullanımım için hasOwnProperty gerekmez; herhangi bir ek javascript işlemesi eklemenin bir anlamı yok. Tüm kullandığım bu:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

18
JSON nesnesinin temiz olup olmadığı önemsizdir. Başka herhangi bir zamanda bazı kodlar bir özelliği Object.prototypeayarlarsa, tarafından numaralandırılır for..in. Bunu yapan herhangi bir kitaplık kullanmadığınızdan eminseniz, aramanıza gerek yoktur hasOwnProperty.
G-Wiz

4
İle oluşturulan eğer tamamen temiz olabilirObject.create(null)
Juan Mendes

20

ile prototip ile ForEach () atlamak prototip zinciri özellikleri:

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

2
Prototip konusunda dikkatli olun: obj = { print: 1, each: 2, word: 3 }üretir TypeError: number is not a function. Kullanılması forEachbenzer eşleşecek şekilde Arrayişlevini biraz riskini azaltabilir.
David Harkness

18

Bu cevapları ilginç insanlar hem dokundu var Object.keys()ve for...offakat bunları kombine asla:

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

Sen sadece can for...ofbir Objectbir yineleyici değil çünkü ve for...indexya .forEach()ing Object.keys()çirkin / verimsizdir.
Çoğu insanın for...in(kontrol ile veya kontrol etmeden .hasOwnProperty()) kaçındığı için memnunum, çünkü bu da biraz dağınık, bu yüzden yukarıdaki cevabım dışında, söylemek için buradayım ...


Sıradan nesne ilişkilendirmelerini yineleyebilirsiniz! Tıpkı davranmak Mapfantezi doğrudan kullanımı ile s for...of
DEMO Chrome ve FF çalışma (ı ES6 varsayalım için)

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);

Şimimi aşağıya eklediğiniz sürece:

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

Güzel sözdizimsel şekeri olmayan gerçek bir Harita nesnesi oluşturmak zorunda kalmadan.

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

Aslında, bu şim ile, hala Harita'nın diğer işlevlerinden yararlanmak istiyorsanız (hepsini daraltmadan), ancak yine de düzgün nesne gösterimini kullanmak istediyseniz, nesneler artık yinelenebilir olduğundan, şimdi sadece bir Harita oluşturabilirsiniz!

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

Şim veya prototypegenel olarak karışıklıktan hoşlanmayanlar için , işlevi pencerede yapmaktan çekinmeyin, bunun yerine o getObjIterator()zamanki gibi bir şey çağırın ;

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

Şimdi bunu sıradan bir işlev olarak adlandırabilirsiniz, başka hiçbir şey etkilenmez

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

veya

for (let pair of getObjIterator(ordinaryObject))

Bunun işe yaramamasının bir nedeni yok.

Geleceğe Hoşgeldiniz.


1
Vaka içinde noktasında . İnsanlar aşağı inip faydalı buldukları sürece, önemli olan budur. Genellikle bir şey yapmaya çalışıyorum, çevrimiçi gördüğüm şeylerden hoşlanmıyorum, sonunda anladım, sonra tekrar paylaşmaya geliyorum. Bu iyi bir doco, aslında tamamen unuttuğum şeyleri araştırmadan önce kendi cevaplarıma rastladım!
Hashbrown

@HelpMeStackOverflowMyOnlyHope Şahsen kendimi tanımlamadığım nesnelerin prototiplerini değiştirmeyi sevmiyorum.
Janus Troelsen

@JanusTroelsen cevabın tamamını bile okudunuz mu? 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

Bu tekniğin düz nesneler üzerinde çalışmadığını, ancak yine de yararlı olduğunu unutmayın.
noɥʇʎԀʎzɐɹƆ

düz nesneler için işe yarıyor, bu tam anlamıyla bütün mesele ( ordinaryObjectve büyünün hala bu türler için çalıştığı vurgu gibi değişken isimler ). Demoları kontrol ettiniz mi? senin için neyin işe yaramadığını, @ noɥʇʎԀʎzɐɹƆ? (PS SE profil resminiz patron)
Hashbrown

13

Object.keys (obj): Dizi

numaralandırılabilir kendi (devralınmamış) özelliklerin tüm dize değerli anahtarlarını alır.

Bu nedenle, her nesne anahtarını hasOwnProperty ile test ederek istediğiniz anahtar listesini verir. Daha Object.keys( obj ).forEach(function( key ){})hızlı olması gerekenden daha fazla test işlemine ihtiyacınız yoktur . Kanıtlayalım:

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.");

Firefox'umda aşağıdaki sonuçlar var

  • Object.keys yaklaşımı 40.21101451665163 milisaniye aldı.
  • for / hasOwnProperty yaklaşımı 98.26163508463651 milisaniye sürdü.

PS. Chrome'da fark daha da büyük http://codepen.io/dsheiko/pen/JdrqXa

PS2: ES6'da (EcmaScript 2015) yinelenebilir nesneyi daha güzel tekrarlayabilirsiniz:

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


{} gösterimini bırakmak istemiyorsanız yine de s of oluşturmadanMap
Hashbrown

13

İşte bir nesne üzerinden yineleme için başka bir yöntem.

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


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


3
Bu çok güzel, ancak büyük nesneler için foryöntem daha performanslı olabilir.
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>


12

Ayrıca, Object.keys () öğesini kullanabilir ve değeri almak için aşağıdaki gibi nesne anahtarları üzerinde yineleme yapabilirsiniz:

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

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


Zamanımı kurtardın, Teşekkür ederim
Swap-IOS-Android

Mutlu olmak :)
Onera

8

Yalnızca bağımlılığı olmayan JavaScript kodu:

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
}

8

Object.keys()Yöntem, belirli bir nesnenin kendi numaralandırılabilir özelliklerinin bir dizi döner. Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz

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

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


8

Verim

Bugün 2020.03.06 Chrome v80.0, Safari v13.0.5 ve MacOs High Sierra v10.13.6'da Firefox 73.0.1'de seçilen çözümlerin testlerini yapıyorum

Sonuçlar

  • for-in(A, B) tabanlı çözümler büyük ve küçük nesneler için tüm tarayıcılar için hızlı (veya en hızlı) çözümlerdir
  • şaşırtıcı bir şekilde for-of(H) çözümü küçük ve büyük nesneler için krom üzerinde hızlıdır
  • açık dizine i(J, K) dayalı çözümler küçük nesneler için tüm tarayıcılarda oldukça hızlıdır (firefox için büyük nesneler için de hızlıdır, ancak diğer tarayıcılarda orta hızlıdır)
  • yineleyicilere (D, E) dayalı çözümler en yavaştır ve önerilmez
  • C çözümü büyük nesneler için yavaş ve küçük nesneler için orta yavaş

resim açıklamasını buraya girin

ayrıntılar

İçin performans testleri yapıldı

  • küçük bir nesne - 3 alanlı - BURADA makinenizde test yapabilirsiniz
  • 'büyük' ​​nesne - 1000 alanla - makinenizde test yapabilirsiniz BURAYA

Snippet'lerin altında kullanılan çözümler sunulmaktadır

Ve işte krom üzerindeki küçük nesneler için sonuç

resim açıklamasını buraya girin


7

Tüm nesnelere basit bir forEach işlevi ekleyebilirsiniz , böylece herhangi bir nesne arasında otomatik olarak döngü yapabilirsiniz:

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

" İçin ... " yöntemini beğenmeyenler için:

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

Şimdi basit bir çağrı yapabilirsiniz:

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

Diğer forEach yöntemleri ile çakışmak istemiyorsanız, bunu benzersiz adınızla adlandırabilirsiniz.


3
Yerleşik nesnelerin (örneğin Object) prototiplerini değiştirmek genellikle bir anti-desen olarak kabul edilir, çünkü diğer kodlarla kolayca çakışmaya neden olabilir. Yani yara bu şekilde yapılmasını önermiyor.
Moritz

6

Saf JavaScript kullanırken döngüler oldukça ilginç olabilir. Sadece ECMA6'nın (Yeni 2015 JavaScript spesifikasyonu) döngüleri kontrol altına aldığı anlaşılıyor. Ne yazık ki bunu yazarken, hem Tarayıcılar hem de popüler Entegre geliştirme ortamı (IDE) hala yeni çanları ve ıslıkları tamamen desteklemeye çalışıyor.

Bir bakışta, bir JavaScript nesne döngüsünün ECMA6'dan önce nasıl göründüğü:

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

Ayrıca, bunun bu soru ile kapsam dışı olduğunu biliyorum, ancak 2011 yılında, ECMAScript 5.1, forEachtemel olarak diziler arasında döngü oluşturmak için yeni geliştirilmiş bir yol yaratan ve eski ayrıntılı ve kafa karıştırıcı fordöngü ile hala yinelenemeyen nesneleri bırakan Diziler yöntemini ekledi . Ancak garip olan, bu yeni forEachyöntemin desteklememesidir breakki bu da her türlü başka soruna yol açmıştır.

Temel olarak 2011'de, birçok popüler kütüphanenin (jQuery, Underscore, vb.) Yeniden uygulamaya karar vermesinden başka JavaScript'te döngü yapmak için gerçek bir sağlam yol yoktur.

2015 itibariyle, artık herhangi bir nesne türünü (Diziler ve Dizeler dahil) döngü (ve kırma) için daha iyi bir yolumuz var. Öneri ana akım haline geldiğinde JavaScript'teki bir döngü sonunda nasıl görünecek:

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

Çoğu tarayıcının 18 Haziran 2016'dan itibaren yukarıdaki kodu desteklemeyeceğini unutmayın. Chrome'da bile çalışması için bu özel bayrağı etkinleştirmeniz gerekir: chrome://flags/#enable-javascript-harmony

Bu yeni standart haline gelene kadar, eski yöntem hala kullanılabilir, ancak popüler kütüphanelerde alternatifler hatta bu kütüphanelerden herhangi birini kullanmayanlar için hafif alternatifler de vardır.


Bu çalışma hakkında bir fikir verebilir misiniz? İşte benim girişimim. jsfiddle.net/abalter/sceeb211
abalter

@abalter Üzgünüm, kodumda bir yazım hatası olduğunu fark ettim. Bunu düzelttim ve JsFiddle'ınızı burada güncelledim: jsfiddle.net/sceeb211/2
Nicolas Bouvrette

Ben krom ve alıyorum Uncaught TypeError: Object.entries is not a function. Henüz kromda uygulanmadı mı?
07'de abalter

@abalter Öyle. Chrome 51 sürümüne sahip olduğunuzdan ve düzenleme ve Jsfiddle yorumlarımda açıklandığı gibi bayrağı etkinleştirdiğinizden emin olun. Ayrıntıları buradan kontrol edebilirsiniz: developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette

Bayrak için özür dilerim. Henüz tam anlamıyla uygulanmış bir özellik olmadığını görüyorum.
abalter

5

ES6'da, daha önce bazı dahili yöntemleri ortaya çıkarmak için iyi bilinen sembollerimiz var, bunu yineleyicilerin bu nesne için nasıl çalıştığını tanımlamak için kullanabilirsiniz:

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

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

bu es6 döngüsünde for ... ile aynı sonucu verecektir.

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

Ama şimdi es6 kullanarak sahip olduğunuz yetenekleri bilmek önemlidir!


1
Özel bir nesne yineleyici tarafından oluşturulan Object.keys()ve bellekte tahsis edilen bir dizi yerleşik dizi yineleyici çağırır ... Serin!
ooo

5

Bunu obj.hasOwnerPropertyher for ... indöngüde kontrol etmek yerine yapardım .

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

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]);
        }
    }
}


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

Bir kullanma for-ofAÇIKObject.keys()

Sevmek:

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

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

4

Numaralandırılamayan özellikler üzerinde de yineleme yapmak istiyorsanız, Object.getOwnPropertyNames(obj)doğrudan belirli bir nesne üzerinde bulunan tüm özelliklerin (numaralandırılabilir veya değil) bir dizisini döndürmek için kullanabilirsiniz .

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/>');
});


2
Bu harika, bu yanıtı gönderdiğiniz için teşekkür ederiz. Bir Errornesneyi introspect gerekiyordu ve bir döngü veya _.forIn(err)çağrı özellikleri alamadım . Kullanmak , daha önce elde edemediğim Object.getOwnPropertyNames(err)tüm parçalara erişmeme izin verdi Error. Teşekkürler!
Pierce

4

Herhangi birinin koşullu arrayObjects arasında döngü yapması gerekiyorsa :

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


4

ES6 göz önüne alındığında, kendi kaşık şekeri eklemek ve nesnenin özellikleri üzerinde yineleme yapmak için bir yaklaşım daha sunmak istiyorum.

Düz JS nesnesi kutudan çıktığı için for..oftekrarlanabilir olmadığından , içeriği üzerinde yineleme yapmak için döngü kullanamıyoruz . Ama kimse bizi tekrarlanabilir kılmak için durduramaz .

Hadi nesnemiz var book.

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

Başardığımızdan bu şekilde kullanabiliriz:

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

Veya ES6 jeneratörlerinin gücünü biliyorsanız, yukarıdaki kodu kesinlikle çok daha kısa yapabilirsiniz.

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

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

}

Elbette, tüm nesneler için bu tür bir davranışı Object, prototypeseviyeye yükseltilebilir hale getirerek uygulayabilirsiniz .

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

Ayrıca, yinelenebilir protokole uyan nesneler yeni ES2015 özellik yayma işleci ile kullanılabilir, böylece nesne özellik değerlerini dizi olarak okuyabiliriz.

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

Veya yıkım atamasını kullanabilirsiniz :

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

Yukarıda sağladığım tüm kodlarla JSFiddle'a göz atabilirsiniz .


Kod değerleri üretecek ama anahtarlar olmadan buldum. Değerleri tuşlarla tekrarlamak mümkün müdür?
Pika

Evet yapabilirsin. "Getiri [anahtar, obj [anahtar]];" ve daha sonra şu şekilde kullanın: {için {}) {} "için [let, [anahtar; değer]]
Artyom Pranovich

4

ES06'dan beri bir nesnenin değerlerini dizi olarak alabilirsiniz

let arrValues = Object.values( yourObject) ;

nesne değerlerinin bir dizisini döndürür ve Prototip'ten değer çıkarmaz !!

MDN DOCS Object.values ​​()

ve anahtarlar için (burada zaten benden önce cevap verdim)

let arrKeys   = Object.keys(yourObject);

Yanıtlar, hem anahtarları hem de değerleri döndüren bir çözüm ister.
Sean Lindo

4

En son ES betiğinde böyle bir şey yapabilirsiniz:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.