JavaScript nesnesi üzerinden yineleme nasıl yapılır?


422

JavaScript'te bir nesnem var:

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

forÖzelliklerini almak için bir döngü kullanmak istiyorum . Ve parçalarda yineleme yapmak istiyorum (bir kerede tüm nesne özellikleri değil).

Basit bir dizi ile standart bir fordöngü ile yapabilirsiniz :

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

Ama nesnelerle nasıl yapılır?


22
Nesne özelliklerinin sırayla depolanmadığını unutmayın. Bir nesne üzerinde yinelediğinizde, görünme sırasına ilişkin bir garanti yoktur.
James Allardice

Yanıtlar:


850

Çoğu nesne için for .. inşunları kullanın :

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

ES6 ile, hem tuşlara hem de değerlere aynı anda ihtiyacınız varsa,

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

Devralınan özelliklerin günlüğe kaydedilmesini önlemek için hasOwnProperty ile kontrol edin :

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

hasOwnPropertyBasit bir nesne (örneğin, kendi yaptığınız nesne) kullanıyorsanız, anahtarları yinelediğinizde kontrol etmenize gerek yoktur {}.

Bu MDN belgeleri daha genel olarak nesnelerle ve bunların özellikleriyle nasıl başa çıkılacağını açıklar.

"Parçalar halinde" yapmak istiyorsanız, en iyisi bir dizideki anahtarları çıkarmaktır. Sipariş garanti edilmediğinden, bu doğru yoldur. Modern tarayıcılarda şunları kullanabilirsiniz:

let keys = Object.keys(yourobject);

Daha uyumlu olmak için bunu yapmanız daha iyi olur:

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

Daha sonra mülklerinizi dizine göre yineleyebilirsiniz yourobject[keys[i]]:

for (let i=300; i < keys.length && i < 600; i++) { 
   console.log(keys[i], yourobject[keys[i]]);
}

3
OP bunu tüm anahtarları tek bir döngüde değil, parçalar halinde yapmak istiyor.
pawel

Evet. Bir döngüde tam nesne değil.
nkuhta

2
@Cerbrus OP zaten bir diziyi parçalar halinde tekrarlamayı bilir. keysVerilen koddan kullanmak yeterli olmalıdır.
Yoshi

2
@Cerbrus Yorum yapmadan önce lütfen okuyun! "Daha uyumlu olmak için bunu yapsan iyi edersin" konusunda net olmayan ne var ?
Denys Séguret

2
@ am05mhz Dediğim gibi, çoğu nesne ile işe yaramaz. Ama herkes için değil. Bunu deneyin: jsbin.com/hirivubuta/1/edit?js,console,output
Denys Séguret

61

İşte modern tarayıcılar için başka bir yineleme çözümü:

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

Veya filtre fonksiyonu olmadan:

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

Ancak, JavaScript nesnesindeki özelliklerin sıralanmadığını, yani herhangi bir siparişin olmadığını düşünmelisiniz.


Döngüyü kıracaksam, bir dahaki sefere nesnenin başından başlayacak, bu doğru yol değil.
nkuhta

21

Object.entriesSeni kullanarak böyle bir şey yap.

 // 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'] ]

Object.entries () yöntemi, belirli bir nesnenin kendi numaralandırılabilir özelliğinin bir dizisini döndürür [anahtar, değer]

Böylece Nesne üzerinde yineleme yapabilir ve nesnenin her biri için ve her birine sahip olabilir keyve valueböyle bir şey elde edebilirsiniz.

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

ya da bunun gibi

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

Referans için Nesne Girişleri için MDN belgelerine göz atın


17

Yeni ES6 / ES2015 özellikleri ile, bir karmayı yinelemek için artık bir nesne kullanmanıza gerek yok. Bir Harita kullanabilirsiniz . Javascript Maps anahtarları ekleme sırasında tutar, yani her zaman gerçekten bir hack olan hasOwnProperty'yi kontrol etmek zorunda kalmadan onları tekrarlayabilirsiniz.

Bir harita üzerinde yineleme yapın:

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"

veya forEach:

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

1
forEach tercih edilen olan
pungggi

14

İsterseniz anahtarı ve değerini ilerlerken, bir kullanabilirsiniz for ... döngü ile 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

7

Bunu yapmanın tek güvenilir yolu, nesne verilerinizi 2 diziye, anahtarlardan birine ve veriler için bir tanesine kaydetmek olacaktır:

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

Daha sonra normalde yaptığınız gibi diziler üzerinde yineleme yapabilirsiniz:

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

Ben kullanmıyorum Object.keys(obj)o IE 9+, çünkü.


3

-> Nesne dizisinin anahtarını kullanarak bir JavaScript nesnesi üzerinde yineleme yaparsak

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

 console.log('key',key)

})

1

Tüm nesneyi bir kerede yinelemek istiyorsanız, loop'u kullanabilirsiniz for in:

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

Ama nesneyi parçalara bölmek istiyorsanız aslında yapamazsınız. Nesnedeki özelliklerin belirtilen sırada olduğuna dair bir garanti yoktur. Bu nedenle iki çözüm düşünebilirim.

Bunlardan birincisi, önceden okunan özellikleri "kaldırmak" tır:

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

Aklıma gelen başka bir çözüm de nesne yerine Array of Arrays kullanmaktır:

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

Ardından, standart fordöngü çalışacaktır.


1

Sonunda Nesneleri, Dizeleri, Dizileri, TypedArrays, Haritalar, Setleri, (herhangi bir Yineleme) yinelemek için birleşik bir arayüz ile kullanışlı bir yardımcı program fonksiyonu ile geldi.

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


1

Lodash - hızlı nesne yinelemesi için modülerlik, performans ve ekstra js sağlayan modern bir JavaScript yardımcı programı kitaplığı kullanmayı deneyebilirsiniz : -

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>


1

Nesne yinelemesi için genellikle bir for..indöngü kullanırız . Bu yapı, prototip kalıtım yoluyla miras alınanlar da dahil olmak üzere tüm numaralandırılabilir özellikler arasında dolaşacaktır . Örneğin:

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

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

Bununla birlikte, for..intüm numaralandırılabilir elemanlar üzerinde döngü yapacak ve bu, parçalardaki yinelemeyi bölmemizi mümkün olmayacaktır. Bunu başarmak için Object.keys(), bir dizideki bir nesnenin tüm anahtarlarını almak için yerleşik işlevi kullanabiliriz. Daha sonra döngüyü yinelemeyi çoklu olarak bölebilir ve keys dizisini kullanarak özelliklere erişebiliriz. Örneğin:

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


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

1
Aslında hayır. Bu, Objectsırayla olduğu anlamına gelir . Onlar değil. If you can make sense of the sentence it workedyalnızca uygulama ayrıntıları nedeniyle çalışır. Hiç çalışacağı garanti edilmez. Ayrıca TitleCase işlevlerinizi ve değişkenlerinizi de yapmamalısınız. Bu classes için.
Florian Wendelborn

0

Gerçekten bir PITA bu standart Javascript'in bir parçası değildir.

/**
 * 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)
    })
}

Not: Geri arama parametrelerini (değer, anahtar) olarak değiştirdim ve API'yi diğer API'larla tutarlı hale getirmek için üçüncü bir nesne ekledim.

Bu şekilde kullanın

const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
    // do something
});

1
sadece ilk cümlede ifadeniz için oy verdi. Değer ilk parametre, dizin veya anahtar ikinci parametre ve üçüncü nesne parametresi olsaydı, bunu forEach () dizisine benzetmek daha iyi olurdu. Gerçi lodash tavsiye öneriyoruz.
SÖZLEŞME DOĞRU

(Değer, anahtar) düzeni fikrini seviyorum. Vue gibi bir kütüphane de böyle yapar. Nesne bağlam olduğundan, ilk parametre olarak düşünülür. Fonksiyonel programlama için oldukça standarttır.
Steven Spungin

Burada kabul ediyorum, ECMA-262, tüm sipariş [değer, dizin, dizi] alan geri çağrıları alan bir forEach (), map (), reduce (), filter (), sahip bir nesne olarak bir dizi tanımlamak için olmasaydı . JS'deki bir nesne sadece başka bir koleksiyon olarak anlaşılabilir; ve sonra bu yöntemler [değer, anahtar | dizin, bağlam] parametrelerinde birleştirilirler (bu, lodash ve alt çizgi bunu yapar). Bence bu "birleşik toplama" protokolü daha güçlü. Ayrıca, nesne bağlam değildir : thisgeri aramanın kendi içeriği olduğundan, geri arama için ne istersen ayarlayabilirsiniz .
SÖZLEŞME DOĞRU

Belki de bunun yerine iş alıcısını kullanmalıydım. Her neyse, hala bir PITA; Parametreleri herhangi bir sırayla memnuniyetle karşılarım.
Steven Spungin

Oh, görüyorum ki birbirimizi yanlış anlamış olabiliriz. Ben her zaman gerçek objectForEachfonksiyonu hakkında değil, geri arama parametreleri ve sıraları hakkında yorum yapıyordum . Bu kafa karıştırıcı olsaydı özür dilerim.
SÖZLEŞME DOĞRU

0

Evet. Döngü için kullanarak bir nesnede döngü yapabilirsiniz. İşte bir örnek

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

NOT: yukarıda belirtilen örnek yalnızca IE9 + 'da çalışacaktır. Objec.keys tarayıcı desteğine bakın burada .


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

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

Çevrimiçi deneyin

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.