İlişkilendirilebilir dizi nesnesinde Javascript foreach döngüsü


182

For-each döngüsü neden JavaScript ilişkisel dizi nesnem üzerinden yinelenmiyor?

// defining an array
var array = [];

// assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

EDIT: jQuery yardımcı each()olabilir: https://api.jquery.com/jQuery.each/


1
Bir dizi oluşturursunuz ancak bir harita olarak kullanırsınız. Bunun yerine düz bir nesne istediğiniz gibi görünüyor.
Jon

4
associative arraysJS'de olduğu gibi bir şey yok : ya düz Array ya da bir Object. Hiçbir şey sayısal olmayan özellikler eklemeyi engellemez Array, ancak bunu yapmaz associative- özellikle, lengthözellik bu özellikleri otomatik olarak saymaz.
raina77ow

3
re: JS'de ilişkisel diziler diye bir şey yoktur. - başka bir şekilde ifade edilir: JavaScript, "ilişkilendirilebilir dizi" adı yerine "Nesne" adını kullanır. Ama bir ".length" özelliği yok.
Jesse Chisholm

Yanıtlar:


315

.lengthÖzellik yalnızca sayısal indeksler (tuşları) ile özelliklerini izler. Anahtarlar için dizeler kullanıyorsunuz.

Bunu yapabilirsiniz:

var arr_jq_TabContents = {}; // no need for an array

arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;

for (var key in arr_jq_TabContents) {
    console.log(arr_jq_TabContents[key]);
}

Güvenli olmak için, özelliklerin hiçbirinin mirasın beklenmedik sonuçları olmadığından emin olmak için böyle döngülerde iyi bir fikirdir:

for (var key in arr_jq_TabContents) {
  if (arr_jq_TabContents.hasOwnProperty(key))
    console.log(arr_jq_TabContents[key]);
}

edit - şimdi Object.keys()işlev modern tarayıcılarda ve Düğüm vb. kullanılabilir olduğunu not etmek iyi bir fikirdir .

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

İletilen geri arama işlevi .forEach(), her bir anahtarla ve döndürülen dizideki anahtarın diziniyle çağrılır Object.keys(). Ayrıca, işlevin yinelendiği diziyi de geçti, ancak bu dizi bizim için gerçekten yararlı değil; orijinal nesneye ihtiyacımız var . Buna doğrudan isimle erişilebilir, ancak (benim görüşüme göre), açıkça geri vermek için biraz daha güzel, ki bu, .forEach()orijinal nesneye - thisgeri çağrıdaki gibi bağlanacak olan ikinci bir argüman geçirerek yapılır . (Bunun aşağıdaki yorumda belirtildiğini gördüm.)


Bu ne var arr_jq_TabContents = {};? Yani {}
Szymon Toda

1
@Ultra boş bir nesne değişmezidir. Bu sadece değişkenin yeni bir boş nesneye referansla başlatıldığı anlamına gelir.
Sivri

@Ultra, bir Array örneğine ihtiyacınız yoktur, çünkü bu kodda bir JavaScript dizisi gibi kullanmıyorsunuzdur. JavaScript, diğer diller gibi "ilişkilendirilebilir diziler" içermez.
Sivri

1
Atama arasındaki fark nedir []ve {}? Sadece farklı prototipler mi?
SoonDead

8
HasOwnProperty kullanmak yerine, tüm modern web tarayıcılarında aşağıdakileri kullanarak bir nesnenin tuşları üzerinde yineleme yapmak mümkün olmalıdır: Object.keys(arr_jq_TabContents).forEach( function(key) { ... } );
Gregory Bell

80

Bu çok basit bir yaklaşım. Avantajı anahtarları da alabilirsiniz:

for (var key in array) {
    var value = array[key];
    console.log(key, value);
}

ES6 için:

array.forEach(value => {
  console.log(value)
})  

ES6 için: (Değer, dizin ve dizinin kendisini istiyorsanız)

array.forEach((value, index, self) => {
  console.log(value, index, self)
})  

12
varMevcut olmayan kapsam belirlemeyi öneren döngülerde kullanmayın . Kullanım vardöngü önünde ya letdöngüde.
ceving

2
@ceving, döngülerde neden var kullanmamanız hakkında daha fazla bilgi verebilir misiniz? C ++ / PHP geçmişinden geliyorum ve bunu anlamıyorum. kapsam belirleme döngü içinde var, ancak geçici, bu yüzden ne demek istediğinden emin değilim.
Dennis

6
@Dennis Çoğu dilde bir fordöngüdeki değişken bir bildirim döngü gövdesi ile sınırlı bir kapsam oluşturur for. Ancak JavaScript'te bildirilen bir değişken var, bir fordöngüde yazsanız bile her zaman global işlev görür . Buraya bakın: davidwalsh.name/for-and-against-let
ceving

1
kendiliğinden bellek sızıntısı değil, kesinlikle "bellek sızıntısı". varJavascript'te döngü tamamlandıktan sonra bile bellekte değişkenler oluşturur.
ahnbizcad

Ben "var" kullanımı ile ilgili bu yorumların amacı şimdi "let" genel olarak ama özellikle bir döngü içinde kullanmak olduğunu düşünüyorum. Sebepler yukarıda açıklanmıştır, ancak özet olarak kapsamdan kaynaklanmaktadır, "var" global kapsam oluşturur.
DeeZone

6

Zaten bazı basit örnekler var, ancak muhtemelen PHP arka planından geldiğini ve JavaScript'in aynı şekilde çalışmasını beklediğiniz sorusunu nasıl ifade ettiğinizi fark ettim. PHP arraybir JavaScript'ten çok farklıdır Array.

PHP'de, ilişkilendirilebilir bir dizi sayısal olarak dizinlenmiş bir dizinin yapabildiklerinin çoğunu yapabilir ( array_*işlevler çalışır, bunu yapabilirsiniz count(), vb.) Basitçe bir dizi oluşturur ve sayısal yerine dize dizinlerine atamaya başlarsınız.

JavaScript'te her şey bir nesnedir (temel öğeler hariç: dize, sayısal, boole) ve diziler sayısal dizinlere sahip olmanızı sağlayan belirli bir uygulamadır. Bir dizi itilmiş şey etkisi olacaktır lengthve (dizi yöntemler kullanılarak fazla yinelenebilen map, forEach, reduce,filter , findo size yaptığım bir şey çünkü her şey bir nesnedir, çünkü sadece atama özellikler serbest zaman sizdedir, Ancak, vs.) herhangi bir nesne. Köşeli ayraç gösterimi, bir mülke erişmenin başka bir yoludur, bu durumda:

array['Main'] = 'Main Page';

aslında şuna eşittir:

array.Main = 'Main Page';

Açıklamanıza göre, tahminim bir 'ilişkilendirici dizi' istediğinizdir, ancak JavaScript için bu, bir nesneyi hashmap olarak kullanmak için basit bir durumdur. Ayrıca, bunun bir örnek olduğunu biliyorum, ancak yalnızca değişken türünü (örneğin array) ve adını içermesi gereken (örn. pages) Temelinde tanımlayan anlamlı olmayan adlardan kaçının . Basit nesnelerin yinelemenin birçok iyi doğrudan yolu yoktur, bu nedenle genellikle Objectyöntemleri kullanarak önce dizilere dönüşürüz ( Object.keysbu durumda - entriesvevalues şu anda bazı tarayıcılar ekleniyor) hangi biz döngü yapamaz.

// assigning values to corresponding keys
const pages = {
  Main: 'Main page',
  Guide: 'Guide page',
  Articles: 'Articles page',
  Forum: 'Forum board',
};

Object.keys(pages).forEach((page) => console.log(page));

4

arr_jq_TabContents[key] diziyi 0-dizin formu olarak görür.


4

İlişkilendirilebilir bir diziyi genel Nesne türü olarak kullanmanın basit bir yolu:

Object.prototype.forEach = function(cb){
   if(this instanceof Array) return this.forEach(cb);
   let self = this;
   Object.getOwnPropertyNames(this).forEach(
      (k)=>{ cb.call(self, self[k], k); }
   );
};

Object({a:1,b:2,c:3}).forEach((value, key)=>{ 
    console.log(`key/value pair: ${key}/${value}`);
});



1

Çoğu durumda bu (esasen) yanlıştır:

var array = [];
array["Main"] = "Main page";

Bu, dizide adıyla öğe olmayan bir özellik oluşturur Main . Diziler nesne olsa da, normalde bunlar üzerinde öğe olmayan özellikler oluşturmak istemezsiniz.

arrayBu adlara göre dizine eklemek istiyorsanız , genellikle birMap bir dizi değil, veya düz bir nesne .

Yaratıcı olduğum için Maparayacağım bir (ES2015 +) ile map:

let map = new Map();
map.set("Main", "Main page");

Daha sonra onun gelen iterators kullanarak yineleme values, keysveya entriesörneğin, yöntemler:

for (const value of map.values()) {
    // Here, `value` will be `"Main page"`, etc.
}

Yaratıcı bir şekilde arayacağım düz bir nesne kullanarak obj:

let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`

Sonra kullanarak içindekileri yineleme ediyorum Object.keys, Object.valuesya da Object.entriesörneğin:

for (const value of Object.values(proches_X)) {
    // Here, `value` will be `"Main page"`, etc.
}

0

var obj = {
  no: ["no", 32],
  nt: ["no", 32],
  nf: ["no", 32, 90]
};

count = -1; // which must be static value
for (i in obj) {
  count++;
  if (obj.hasOwnProperty(i)) {
    console.log(obj[i][count])
  };
};

Bu kodda ben dizi içerdiği için dizi çağrı değerleri için parantez yöntemi kullanılır, ancak kısaca bir değişken i bir özellik anahtarı olan ve ilişkilendirme dizisinin her iki değeri denilen bir döngü ile fikir

mükemmel Yöntem, eğer ilgileniyorsanız, gibi basın


Bir dizi atma döngüsünü yapmıyorsunuz, anahtarlarında dizileri olan bir nesneyi düşündünüz. Lütfen soruyu okuyun ve örneğe bakın.
Pedro Joaquín

0

Bunu yapabilirsiniz

var array = [];

// assigning values to corresponding keys
array[0] = "Main page";
array[1] = "Guide page";
array[2] = "Articles page";
array[3] = "Forum board";


array.forEach(value => {
    console.log(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.