JavaScript'te bir dizi arasında geçiş yapma


3145

Java'da for, bir dizideki nesneleri aşağıdaki gibi dolaşmak için bir döngü kullanabilirsiniz :

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

Aynı şeyi JavaScript'te de yapabilir misiniz?


5
Tamam, bu yüzden biraz kafam karıştı, nesnelere erişirken gelişmiş for döngüsünü kullanmak tamam mı? Ve birini doldurmak için sıralı bir tane mi kullanıyorsunuz? Bu doğru mu?
Mark Szymanski

45
Hayır, gerçekten basittir, dizi nesnelerinin sayısal dizinleri vardır, bu nedenle bu dizinleri sayısal sırayla yinelemek istersiniz , sıralı bir döngü, gelişmiş for-in döngünün belirli bir düzen olmadan nesne özelliklerini numaralandırmasını ve ayrıca devralınan özellikleri numaralandırmasını sağlar. .. diziler üzerinde yineleme için sıralı döngüler her zaman tavsiye edilir ...
CMS


6
jsben.ch/#/Q9oD5 <= Burada diziler arasında döngü için bir grup çözümün karşılaştırması
EscapeNetscape

3
@CMS Hayır, gerçekten basit değil. Diğer her dilde gerçekten basit. Sahip olduğunuz inve ofhem farklı hem de farklı şeyler yapabileceğiniz JS'de gülünç derecede karmaşık . Sonra da forEachve çirkin ve sinir bozucu dizin tabanlı döngü var. Diğer tüm modern diller, bir koleksiyon üzerinde döngü oluşturmayı sürprizler ve karışıklıklar olmadan kolay ve anlaşılır hale getirir. JS de yapabilirdi, ama değil.
jpmc26

Yanıtlar:


3961

Birkaç seçeneğiniz var:

1. Sıralı fordöngü:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    console.log(myStringArray[i]);
    //Do something
}

Artıları

  • Her ortamda çalışır
  • Akış ifadelerini kullanabilir breakve continueakış kontrol edebilirsiniz

Eksileri

  • Çok ayrıntılı
  • Zorunlu
  • Tek tek hatalara sahip olmak kolaydır (bazen çit sonrası hatası da denir )

2. Her Dizi için dizi prototipi

ES5 belirtimi, bunlardan biri olan birçok faydalı dizi yöntemi tanıttı Array.prototype.forEachve bize bir dizi üzerinde yineleme yapmak için özlü bir yol sunuyor:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

ES5 spesifikasyonunun piyasaya sürülme tarihi olarak neredeyse on yıl olan (Aralık 2009), masaüstü, sunucu ve mobil ortamlardaki neredeyse tüm modern motorlar tarafından uygulandı, bu yüzden bunları kullanmak güvenlidir.

Ve ES6 ok işlevi sözdizimi ile daha da özlü:

array.forEach(item => console.log(item));

Eski platformları (ör. IE11) desteklemeyi planlamadığınız sürece ok işlevleri de yaygın olarak uygulanır; ayrıca güvenle gidebilirsiniz.

Artıları

  • Çok kısa ve özlü.
  • bildiren

Eksileri

  • Kullanamıyorum break/continue

Normalde, breakdizi öğelerini yinelemeden önce filtreleyerek zorunlu döngülerden çıkma ihtiyacını değiştirebilirsiniz, örneğin:

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

Ondan başka bir dizi oluşturmak için bir dizi yineliyorsanız , kullanmalısınız map, bu anti-paterni birçok kez gördüm.

Anti-kalıbı:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

Haritanın uygun kullanım durumu :

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

Ayrıca, diziyi bir değere indirmeye çalışıyorsanız , örneğin bir sayı dizisini toplamak istiyorsanız, reduce yöntemini kullanmalısınız .

Anti-kalıbı:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

Uygun kullanımı azaltmak :

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. ES6 for-ofbildirimi

ES6 standardı, yinelenebilir nesneler kavramını tanıtır ve veri aktarımı için yeni bir yapı tanımlar for...of.

Bu ifade, her türlü yinelenebilir nesne ve ayrıca jeneratörler (bir [Symbol.iterator]özelliği olan herhangi bir nesne ) için çalışır.

Dizi nesneleri tanım gereği ES6'da yerleşik yinelenebilir niteliktedir, bu nedenle bu ifadeyi bunlarda kullanabilirsiniz:

let colors = ['red', 'green', 'blue'];
for (const color of colors){
    console.log(color);
}

Artıları

  • Çok çeşitli nesneler üzerinde yineleme yapabilir.
  • Normal akış kontrol ifadelerini kullanabilir ( break/continue ).
  • Seri eşzamansız değerleri yinelemek için kullanışlıdır.

Eksileri

Kullanmayın for...in

@zipcodeman ifadenin kullanılmasını önerir for...in, ancak yinelenen dizilerden for-inkaçınılmalıdır, bu ifade nesne özelliklerini numaralandırmak .

Dizi benzeri nesneler için kullanılmamalıdır çünkü:

  • Yineleme sırası garanti edilmez; dizi dizinleri sayısal sırada ziyaret edilemeyebilir.
  • Devralınan özellikler de numaralandırılır.

İkinci nokta, size birçok sorun verebilmesidir, örneğin, Array.prototype nesneyi orada bir yöntem içerecek şekilde , bu özellik de numaralandırılır.

Örneğin:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
    console.log(array[i]);
}

Yukarıdaki kod, günlük kaydı "a", "b", "c" ve "foo!"

Özellikle yerel prototiplerin güçlendirilmesine (örneğin MooTools gibi) dayanan bir kütüphane kullanıyorsanız, bu özellikle bir sorundur.

Daha for-inönce söylediğim gibi nesne özelliklerini numaralandırmak için orada , örneğin:

var obj = {
    "a": 1,
    "b": 2,
    "c": 3
};

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) { 
        // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

Yukarıdaki örnekte, hasOwnPropertyyöntem yalnızca kendi özelliklerini numaralandırmanıza izin verir , işte bu, yalnızca nesnenin fiziksel olarak sahip olduğu özellikler, kalıtsal özellikler yoktur.

Aşağıdaki makaleyi okumanızı tavsiye ederim:


21
Nedeni (CMS tarafından kendi kendine) stackoverflow.com/questions/1885317/…
OscarRyz

15
@DoubleGras, bunun herkes tarafından paylaşılmayan bir görüş olduğunu düşünüyorum. Bkz. Stackoverflow.com/questions/5752906/… veya groups.google.com/forum/?fromgroups#!topic/jsmentors/…
Matthijs Wessels

3
Uzunluğu önbelleğe almanız gerektiğini düşünen herkes ... Lütfen cevabımı görün, önbelleğe almasına izin vermek yerine, tek bir kez erişmenize bile gerek yok: for (var i = 0, item; item = myStringArray [i]; i ++) {/ * burada öğeyi kullanın * /}
Stijn de Witt

15
@StijndeWitt Hayır, bu sonları çünkü eğer varsa "Falsey" sizin dizideki değerleri: false, undefined, 0, "", NaN.
Phrogz

6
jsperf.com/caching-array-length/4 Bir Javascript döngüsünde bir dizinin uzunluğunu önbelleğe almaya değer olup olmadığını görmek için bir test
Enrico

1114

Evet, uygulamanızın ECMAScript 2015'te tanıtılan for...of özelliğini ("Uyum" sürümü) içerdiğini varsayarsak, bu günlerde oldukça güvenli bir varsayımdır.

Şöyle çalışır:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

Daha da iyisi, ECMAScript 2015 ayrıca blok kapsamındaki değişkenleri de sağladığından:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

(Değişken sher yinelemede farklıdır, ancak yine de constdeğiştirilmediği sürece döngü gövdesi içinde bildirilebilir .)

Seyrek dizilerle ilgili bir not: JavaScript'teki bir dizi aslında rapor ettiği kadar öğe depolamayabilir length; bildirilen sayı, bir değerin saklandığı en yüksek dizinden yalnızca bir daha büyüktür. Dizi, uzunluğuyla belirtilenden daha az öğe içeriyorsa, seyrek olduğu söylenir . Örneğin, yalnızca 3, 12 ve 247 dizinlerinde öğeler içeren bir dizi olması tamamen meşrudur; Eksik elemanları ler veya yalnızca fiilen mevcut elemanlarını işlemek istiyorsun? Her iki yaklaşım için de birçok uygulama vardır; sadece diziyi ne için kullandığınıza bağlıdır.length tür bir dizinin 248 olduğu rapor edilir, ancak sadece 3 değer depolar. Başka bir dizindeki bir öğeye erişmeye çalışırsanız, dizi undefinedorada bir değere sahip gibi görünür . Bu nedenle, bir diziyi "döngüye sokmak" istediğinizde, yanıtlayacağınız bir sorunuz vardır: uzunluğu ve işlemi ile belirtilen tüm aralıkta döngü yapmak istiyor musunuzundefined

for.. ile bir dizi üzerinde yinelerseniz of, döngü gövdesi yürütülür lengthve döngü denetim değişkeni undefineddizide gerçekte bulunmayan öğeler için olarak ayarlanır . "Şununla bir şeyler yap" kodunuzun ayrıntılarına bağlı olarak, bu davranış istediğiniz gibi olabilir, ancak değilse, farklı bir yaklaşım kullanmalısınız.

Tabii ki, bazı geliştiriciler çarem yok ama çünkü onlar henüz desteklemediği bir JavaScript sürümünü hedeflediğiniz Sebebi ne olursa olsun, yine de farklı bir yaklaşım kullanmak for... of.

JavaScript uygulamanız ECMAScript belirtiminin önceki sürümüyle (örneğin, Internet Explorer'ın 9'dan önceki sürümlerini hariç tutan) uyumlu olduğu sürece, Array#forEachdöngü yerine yineleyici yöntemini kullanabilirsiniz . Bu durumda, dizideki her öğeye çağrılacak bir işlev iletirsiniz:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

Bunun aksine for... of, .forEachişlevi yalnızca dizide bulunan öğeler için çağırır. Varsayımsal dizimizi üç eleman ve 248 uzunluk ile geçtiyse, fonksiyonu 248 kez değil, sadece üç kez çağıracaktır. Ayrıca, eksik öğeler ile gerçekte ayarlanmış öğeler arasında ayrım yapar undefined; ikincisi için, undefinedargüman olarak geçerek hala işlevi çağırır . Bu seyrek diziler nasıl ele almak istediğinizi ise, .forEachhatta tercüman destekliyorsa gitmek için bir yol olabilir for... of.

JavaScript'in tüm sürümlerinde çalışan son seçenek, açık bir sayma döngüsüdür . Sadece 0'dan uzunluktan bire daha az sayın ve sayacı dizin olarak kullanın. Temel döngü şöyle görünür:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  s = myStringArray[i];
  // ... do something with s ...
}

Bu yaklaşımın bir avantajı, seyrek dizilerin nasıl ele alınacağını seçebilmenizdir; Yukarıdaki kod döngü tam gövdesini çalışacak lengtholan kat setmek seti undefinedgibi, eksik elemanlar için for.. of. Bunun yerine, örneğin .forEach, seyrek bir dizinin yalnızca mevcut öğelerini işlemek istiyorsanız in, dizine basit bir test ekleyebilirsiniz :

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Uzunluk değişkenini yerel değişkene atamak ( myStringArray.lengthdöngü ifadesine tam ifadeyi eklemek yerine ), her seferinde bir özellik aramasını atladığından performansta önemli bir fark yaratabilir; makinemde Rhino kullanarak hızlanma% 43.

Döngü başlatma yan tümcesinde yapılan uzunluk önbelleğini görebilirsiniz, şöyle:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

Açık sayım döngüsü, isterseniz her bir değerin dizinine erişiminiz olduğu anlamına gelir. Dizin ayrıca geçtiğiniz işleve fazladan bir parametre olarak iletilir forEach, böylece ona da bu şekilde erişebilirsiniz:

myStringArray.forEach( function(s, i) {
   // ... do something with s and i ...
});

for... ofSize her nesne ile ilişkilendirilmiş dizinini verin, ama sürece üzerinde yineleme ediyoruz nesne olarak aslında bir vermezse Array( for.. ofbu yöntemi olmayabilir diğer iterable türleri için işleri), kullanabilirsiniz Dizisi #entries yöntemi bir [index, item] çift dizisine dönüştürür ve ardından bunu yineler :

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

for... inbaşkaları tarafından bahsedilen sözdizimi bir nesnenin özellikleri üzerinde döngü içindir; JavaScript'teki bir Array yalnızca sayısal özellik adlarına (ve otomatik olarak güncellenen bir lengthözelliğe) sahip bir nesne olduğundan , teorik olarak onunla bir Array üzerinde döngü oluşturabilirsiniz. Ancak sorun, kendisini sayısal özellik değerleriyle sınırlamamasıdır (yöntemlerin bile sadece değeri bir kapatma olan özellikler olduğunu unutmayın) ya da sayısal sırayla olanlar üzerinde yineleme yapması garanti edilmez. Bu nedenle, for... insözdizimi gerektiğini değil Diziler yoluyla aktarılması için kullanılabilir.


21
Bazı tercümanlar (örn V8) otomatik olarak dizinin uzunluğunu önbelleğe olacağı Not eğer kod yeterli kez adı verilir ve uzunluk döngü tarafından değiştirilmez algılar. Uzunluğu önbelleğe almak hala güzel olsa da, kodunuz gerçekten bir fark yaratmak için yeterince kez çağrıldığında bir hız artışı sağlamayabilir.
Phrogz

2
@ mark-reed Örneğinizde neden kullandığınızı açıklayabilir misiniz i in myStringArray? Bu nasıl yanlış olabilir?
Denis V

2
@DenisV: yanlış. a=[1,2,3,4]; delete a[2]; for (j in a) { console.log(j); } 0, 1, 3 ve 4 çıkışları a.lengthhala 5'tir.
Mark Reed

1
Ben önermiyorum for j in a. inTüm dizinleri göstererek ve 0 arasında bir tane olduğunu ve orada olmadığını göstererek , denetimin iddia ettiğiniz gibi gereksiz olmadığını gösteriyorum length-1. Ayrıca , imkansız olduğunu söylemiş olmanıza rağmen 2 in a, gerçekten de basmış olabilirdim false.
Mark Reed

2
@GrijeshChauhan - doğru. Örneğin, IE sürümü 8 ile bunu desteklemiyor. Bu soruya bakın .
Mark Reed

442

Sen kullanabilirsiniz mapda benzeri diğer dillerde mevcut olan bir fonksiyonel programlama tekniğidir olan Python ve Haskell .

[1,2,3,4].map( function(item) {
     alert(item);
})

Genel sözdizimi:

array.map(func)

Genel funcolarak, dizinin bir öğesi olan bir parametre alır. Ancak JavaScript durumunda, öğenin dizini olan ikinci bir parametre ve dizinin kendisi olan üçüncü bir parametre alabilir.

Dönüş değeri array.mapbaşka bir dizidir, bu nedenle bunu şu şekilde kullanabilirsiniz:

var x = [1,2,3,4].map( function(item) {return item * 10;});

Ve şimdi x öyle [10,20,30,40].

İşlevi satır içine yazmak zorunda değilsiniz. Ayrı bir işlev olabilir.

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

bu da şuna eşdeğer olacaktır:

 for (item in my_list) {item_processor(item);}

Dışında alamıyorum new_list.


7
Hayır, ama daha güçlü olabilir. Şuna bir
hasen

97
Bu özel örnek muhtemelen daha iyi uygulanır Array.forEach. mapyeni bir dizi oluşturmak içindir.
harto

21
@hasen, Array.prototype.mapyöntem ECMAScript 5. Baskı Standardının bir parçasıdır, henüz tüm uygulamalarda (örneğin IE eksikleri) mevcut değildir, ayrıca bir dizi üzerinden yineleme için de Array.prototype.forEachyöntem daha semantik olarak doğrudur ... ayrıca lütfen yapma ' t for-in önerisini önerin, daha fazla bilgi için cevabımı görün :)
CMS

3
Arasındaki fark forEachve mapeski tekrarlamanın sonuç olmamasıdır. map(bazen aka collect, ama çok farklı apply) bir dizinin her bir elemanını karşılık gelen bir sonuca dönüştürmek içindir; Bir 1-to-1 var haritalama , dolayısıyla adı. Bu, reduce(tüm diziden tek bir sonuç üreten) ve filter(orijinal dizinin bir alt kümesini üreten) vb. İçeren bir dizi işlem ailesinin parçasıdır . Oysa forEachher bir öğe için bir şeyler yaparken, anlambilim belirtilmemiş.
Mark Reed

4
Gerçekten bir şey eşlemiyorsanız, [] .map komutunu kullanmak yanıltıcıdır. [] .forEach semantik mantıklıdır ve aynı üç argümanı işleve iletir.
gengkev

120

JavaScript'te, for-in döngüsüne sahip bir Array'da döngü yapmanız önerilmez, ancak aşağıdaki forgibi bir döngü kullanmak daha iyidir :

for(var i=0, len=myArray.length; i < len; i++){}

Aynı zamanda optimize edilmiştir (dizi uzunluğunu "önbelleğe alır"). Daha fazla bilgi edinmek isterseniz , konu hakkındaki yazımı okuyun .


2
myArray.forEach (function (obj) {}); hala en iyisi
Jan Sverre

küçük bir gelişme: ++iyerine kullanabilirsinizi++
roberkules

14
++imodern derleyicilerin sizin için uzun bir zaman önce bir döngü için yaptığı eski bir okul optimizasyonu :) stackoverflow.com/a/1547433/1033348
ngryman

6
Bu döngüyü kullanırken dikkatli olmalısınız. Kullanmaya başladım ve yaptığım bir hata nedeniyle hatayı izlemek zor oldu. Böyle iki döngüyü iç içe yerleştirirseniz: jsfiddle.net/KQwmL/1 . Değişken'i iki döngüde farklı bir şekilde adlandırmaya dikkat etmelisiniz, aksi takdirde ikinci döngü ilk len'in üzerine yazacaktır.
Rui Marques

1
Rui Marques - değişkeninizi adlandırabilirsiniz i_stopveya i_endyerine len. Sadece okunabilir (daha fazla değilse!) Ve doğal olarak bu tür bir problemden kaçınacaksınız (çünkü diğer döngünüz alacaktır, örneğin j_stop).
Chip Hogg

119

for (hadi myStringArray) {

(Sorunuzu doğrudan cevaplayın: şimdi yapabilirsiniz!)

Diğer cevapların çoğu doğrudur, ancak ECMA Script  6  2015'in yineleme, for..ofdöngü için yeni bir mekanizma getirdiğini belirtmemektedirler .

Bu yeni sözdizimi, bir diziyi javascript'te yinelemenin en zarif yoludur (yineleme dizinine ihtiyacınız olmadığı sürece).

Şu anda Firefox 13+, Chrome 37+ ile çalışır ve diğer tarayıcılarla yerel olarak çalışmaz (aşağıdaki tarayıcı uyumluluğuna bakın). Neyse ki bugün yeni nesil özellikleri kullanmamızı sağlayan JS derleyicileri ( Babel gibi ) var.

Ayrıca Düğüm üzerinde çalışır (0.12.0 sürümünde test ettim).

Diziyi yineleme

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

Bir dizi nesneyi yineleme

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var member of band){
  console.log(member.firstName + ' ' + member.lastName); 
}

Jeneratörü yineleme:

(örnek, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of adresinden alınmıştır )

function* fibonacci() { // a generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Uyumluluk tablosu: http://kangax.github.io/es5-compat-table/es6/#For..of döngüler

Spesifikasyon: http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}


Eğer ES6 kullanıyorsanız, öneririm const syerinevar s
joeytwiddle

Büyük dizilerdeki testlerimde, var s of arrnodejs'de basit bir döngü için sayaç sayma ve elemanları indekse göre alma ile karşılaştırıldığında yürütme süresi neredeyse iki kattır (1,9x)
theferrit32

Neden ilk ve son satırdaki tuhaf şeyler?
Peter Mortensen

91

Opera, Safari, Firefox ve Chrome artık birçok ortak döngüyü optimize etmek için bir dizi gelişmiş Dizi yöntemini paylaşıyor.

Hepsine ihtiyacınız olmayabilir, ancak çok yararlı olabilirler veya her tarayıcı bunları destekliyorsa olabilir.

Mozilla Labs, WebKit'in ve WebKit'in kullandığı algoritmaları yayınladı , böylece bunları kendiniz ekleyebilirsiniz.

filtresi , bazı koşulları veya testleri karşılayan bir öğe dizisi döndürür.

Her dizi üyesi testi geçerse her biri true değerini döndürür.

bazıları testi geçerse true değerini döndürür.

forEach her dizi üyesi üzerinde bir işlev çalıştırır ve hiçbir şey döndürmez.

map forEach gibidir, ancak her öğe için işlem sonuçlarının bir dizisini döndürür.

Bu yöntemlerin tümü ilk bağımsız değişkenleri için bir işlev alır ve isteğe bağlı ikinci bağımsız değişkene sahiptir; bu, kapsamı işlev boyunca döngü üyeleri olarak dizi üyelerine dayatmak istediğiniz bir nesnedir.

İhtiyacınız olana kadar yok sayın.

indexOf ve lastIndexOf , bağımsız değişkeniyle tam olarak eşleşen ilk veya son öğenin uygun konumunu bulur.

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();

1
Ek: IE, sürüm 9'dan beri
forEach'ı

75

giriş

Üniversitedeki zamanımdan beri Java, JavaScript, Pascal, ABAP'de program yaptım , PHP, Progress 4GL, C / C ++ ve muhtemelen şu anda düşünemediğim birkaç dilde programladım.

Hepsinin kendi dilbilimsel özerklikleri olmasına rağmen, bu dillerin her biri aynı temel kavramların çoğunu paylaşır. Bu tür kavramlar prosedürleri / işlevleri, IF-tatimleri, FOR-döngüleri ve- WHILEdöngülerini içerir.


Geleneksel- fordöngü

Geleneksel bir fordöngü üç bileşene sahiptir:

  1. Başlatma: görünüm bloğu ilk kez yürütülmeden önce yürütülür
  2. Koşul: döngü bloğu yürütülmeden önce bir koşulu kontrol eder ve yanlışsa döngüden çıkar
  3. Sonradan düşünülmüş: döngü bloğu yürütüldükten sonra her seferinde gerçekleştirilir

Bu üç bileşen birbirinden bir ;sembol ile ayrılır . Bu üç bileşenin her biri için içerik isteğe bağlıdır, yani aşağıdakiler mümkün olan en düşük fordöngüdür:

for (;;) {
    // Do stuff
}

Tabii ki, çalışmayı durdurmak için bu döngüye bir if(condition === true) { break; } veya bir yer eklemeniz gerekecek .if(condition === true) { return; }for

Genellikle, başlatma işlemi bir dizin bildirmek için kullanılır, koşul bu dizini minimum veya maksimum değerle karşılaştırmak için kullanılır ve sonradan gelenler dizini artırmak için kullanılır:

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

forBir dizi arasında döngü yapmak için geleneksel bir döngü kullanma

Bir dizide döngü yapmanın geleneksel yolu şudur:

for (var i = 0, length = myArray.length; i < length; i++) {
    console.log(myArray[i]);
}

Veya, geriye doğru döngü yapmayı tercih ederseniz, bunu yaparsınız:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

Bununla birlikte, örneğin bunun gibi birçok varyasyon mümkündür:

for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
    console.log(value);
}

...ya da bu...

var i = 0, length = myArray.length;
for (; i < length;) {
    console.log(myArray[i]);
    i++;
}

...ya da bu:

var key = 0, value;
for (; value = myArray[key++];){
    console.log(value);
}

Hangisi daha iyi çalışıyorsa, büyük ölçüde hem kişisel zevkiniz hem de uyguladığınız özel kullanım durumu söz konusudur.

Bu varyasyonların her birinin, çok eski olanlar da dahil olmak üzere tüm tarayıcılar tarafından desteklendiğini unutmayın!


Bir whiledöngü

Döngüye bir alternatif for, bir whiledöngüdür. Bir dizi arasında geçiş yapmak için şunları yapabilirsiniz:

var key = 0;
while(value = myArray[key++]){
    console.log(value);
}

Geleneksel fordöngüler gibi, whiledöngüler de en eski tarayıcılar tarafından desteklenir.

Ayrıca, while while döngüsünün loop olarak yeniden yazılabileceğini unutmayın for. Örneğin, whiledöngü bu döngü ile aynı şekilde davranır for:

for(var key = 0; value = myArray[key++];){
    console.log(value);
}

For...in ve for...of

JavaScript'te şunları da yapabilirsiniz:

for (i in myArray) {
    console.log(myArray[i]);
}

Bununla birlikte, bu, forher durumda geleneksel bir döngü ile aynı şekilde davranmadığı ve dikkate alınması gereken potansiyel yan etkiler olduğu için dikkatli kullanılmalıdır . Bkz "in için ..." Neden kullanıyor diziye yineleme kötü bir fikir ile?daha fazla ayrıntı için.

Alternatif olarak for...in, şimdi de var for...of. Aşağıdaki örnek, bir for...ofdöngü ile döngü arasındaki farkı gösterir for...in:

var myArray = [3, 5, 7];
myArray.foo = "hello";

for (var i in myArray) {
  console.log(i); // logs 0, 1, 2, "foo"
}

for (var i of myArray) {
  console.log(i); // logs 3, 5, 7
}

Ayrıca, hiçbir Internet Explorer sürümünün for...of( Edge 12+ desteklemediğini) desteklemediğini ve for...inen az Internet Explorer 10 gerektirdiğini düşünmeniz gerekir .


Array.prototype.forEach()

Aşağıdaki sözdizimini kullanan for-loops seçeneğine bir alternatif Array.prototype.forEach():

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

Array.prototype.forEach() Internet Explorer 9 ve sonraki sürümlerin yanı sıra tüm modern tarayıcılar tarafından desteklenir.


Kütüphaneler

Son olarak, birçok yardımcı program kütüphanesinin de kendi foreachvaryasyonu vardır. AFAIK, en popüler üç tanesi:

jQuery.each(), jQuery'de :

$.each(myArray, function(key, value) {
    console.log(value);
});

_.each(), Underscore.js'de :

_.each(myArray, function(value, key, myArray) {
    console.log(value);
});

_.forEach(), Lodash.js'de :

_.forEach(myArray, function(value, key) {
    console.log(value);
});

68

While döngüsünü kullanın ...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

günlükleri: 'bir', 'iki', 'üç'

Ve ters sipariş için daha da verimli bir döngü

var items = ['one','two','three'], i = items.length;
while(i--){
    console.log(items[i]);
}

günlükleri: 'üç', 'iki', 'bir'

Veya klasik fordöngü

var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

günlükleri: 'bir', 'iki', 'üç'

Referans: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


21
Dizi öğelerinden herhangi biri yanlışsa "while" sözdiziminin ilk örneği çalışmaz.
Chris Cooper

2
... ve bu while döngüsü şununla eşdeğerdir: for (var i = 0, item; item = items [i]; i ++), dizin ve öğe değişkenlerini önceden bildirme ihtiyacını ortadan kaldırır ...
Stijn de Witt


39

Hızlı bir döngü yazmak için kısa bir yol istiyorsanız ve tersine yineleyebilirsiniz:

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

Bu, yazacak daha az karakter olurken uzunluğu önbelleğe almanın (benzer for (var i=0, len=myArray.length; i<len; ++i)ve farklı olmayan for (var i=0; i<myArray.length; ++i)) avantajına sahiptir .

Hatta, yineleme sırasında tersine yinelemeniz gerektiğinde, örneğin, yineleme sırasında DOM'dan öğeleri kaldırmayı planladığınız canlı bir Düğüm Listesi üzerinden yineleme yaparken bile .


16
Bu kadar dahiyane olanı elde edemeyen insanlar için: i- ifadesi önce değerlendirilir ve döngünün sahte olmadığında devam etmesine izin verir ... Daha sonra sayaç azaltılır. Ben sıfır olur olmaz sıfır Javascript bir sahte bir değer olduğu için döngü kırılır.
Stijn de Witt

5
falsish? Falsey demek istiyorsun.
Hepimiz

4
Gurur terimini guru olarak düşündüğüm insanlar tarafından kullanıldığını gördüm. Onlar için yeterince iyiyse, benim için yeterince iyidir. Ayrıca bir ama aslında ontopik ve açıklama / fikir ekleyen benim yorum 0 upvotes, ama benim yorumda bir terim nitpicks 4 yorum alır görmek için hayal kırıklığına uğradım 4. Ah iyi sadece öncelikler meselesi sanırım.
Stijn de Witt

"Uzunluk önbellekleme"? Uzunluk dizide bir tamsayı olarak saklanır, her eriştiğinizde ölçülmez. Burada uzunluk değerini başka bir değişkene kopyalamanın bir yararı yoktur.
Mouscellaneous

1
@Mouscellaneous Bugünlerde kesinlikle yok; JavaScript yinelemesini geçmiş yıllarda JavaScript tarafında uzunluğu önbelleğe almak (uygulama genelinde ulaşmak yerine) net bir kazanç (mikrooptimizasyon yaparken) oldu. Örneğin, for (var i=0,len=array.length;i<len;++i)yazmak için yaygın ve mantıklı bir döngü oldu.
Phrogz

36

Bazıları JavaScript'te işlevsel programlama yolunda bir dizi üzerinden döngü halini kullanır :

1. Sadece bir dizi üzerinden döngü

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

Not: Array.prototype.forEach (), giriş parametresi olarak aldığı işlevin saf bir işlev olarak kabul edilemeyen bir değer döndürmesi gerekmediğinden, kesin olarak konuşmak için işlevsel bir yol değildir.

2. Bir dizideki elemanlardan herhangi birinin bir testi geçip geçmediğini kontrol edin

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3. Yeni bir diziye dönüştürün

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

Not: map () yöntemi, çağıran dizideki her öğede sağlanan bir işlevi çağırmanın sonuçlarıyla yeni bir dizi oluşturur.

4. Belirli bir mülkü toplayın ve ortalamasını hesaplayın

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5. Orijinali temel alan ancak değiştirmeden yeni bir dizi oluşturun

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6. Her kategorinin sayısını sayın

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7. Belirli ölçütlere göre bir dizinin alt kümesini alma

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

Not: filter () yöntemi, sağlanan işlev tarafından uygulanan sınamayı geçen tüm öğeleri içeren yeni bir dizi oluşturur.

8. Diziyi sıralama

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

resim açıklamasını buraya girin

9. Dizideki bir öğeyi bulma

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

resim açıklamasını buraya girin

Array.prototype.find () yöntemi, dizideki sağlanan test işlevini karşılayan ilk öğenin değerini döndürür.

Referanslar


30

Döngünüzde çok az örtülü kapsamın olduğu ve ekstra değişkenlerle ortadan kaldırmanın bir yolu var.

var i = 0,
     item;

// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){ 
    item; // This is the string at the index.
}

Ya da gerçekten kimliği almak ve gerçekten klasik bir fordöngüye sahip olmak istiyorsanız :

var i = 0,
    len = myStringArray.length; // cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

Modern tarayıcılar tüm destek yineleyici yöntemleri forEach, map, reduce, filterve diğer yöntemlerle bir dizi Dizi prototip .


3
Kod yeterli kez çağrılırsa ve uzunluğun döngü tarafından değiştirilmediğini algılarsa, bazı tercümanların (örneğin V8) dizinin uzunluğunu otomatik olarak önbelleğe alacağını unutmayın.
Phrogz

@Phrogz info için teşekkürler, VM'nin yapabileceği birçok optimizasyon olduğu doğrudur, ancak eski tarayıcılar buna sahip olmadığından, çok ucuz olduğu için optimizasyon yapmak hala en iyi uygulama olacaktır.
Gabriel

1
@ Gabriel: Neden? Lütfen uzunluğu önbelleğe almamanın aslında bir performans darboğazı olduğunu gösteren gerçek dünyadan örnekler verin. Ben 'erken optimizasyon tüm kötülüklerin kökü' yaklaşımını takip ediyorum. Karşılaştığımda bir sorun teşkil eden bir döngüyü düzeltirim ...
Stijn de Witt

1
@StijndeWitt imo sadece stilistik bir konudur. Dürüst olmak gerekirse, artık bu şeyleri yapmak için _.each, _.map vs. gibi şeyler için alt çizgiye güvenen döngüler için bile kullanmıyorum. Bunun gibi döngüler yazdığımda, öncelikle tüm değişken bildirimin tek bir yerde, fonksiyonumun üstünde olması için uzunluğu önbelleğe aldım. Bu konuda tavsiyemi takip etmek, herhangi bir gerçek dünya uygulaması için önemsizdir. Erken optimizasyon çok kötü, ancak optimizasyon stilistik kararlardan kaynaklanıyorsa bunun gerçekten önemli olduğunu düşünmüyorum.
Gabriel

1
@Gabriel JavaScript'in dizilerdeki harita işlevini zaten desteklediğine inanıyorum, bunun için ek bir lib kullanmaya gerek yok.
Noz

28

JavaScript'te dizi arasında geçiş yapmanın çeşitli yolları vardır.

Genel döngü:

var i;
for (i = 0; i < substr.length; ++i) {
    // Do something with `substr[i]`
}

Her biri için ES5'ler:

substr.forEach(function(item) {
    // Do something with `item`
});

jQuery.each:

jQuery.each(substr, function(index, item) {
    // Do something with `item` (or `this` is also `item` if you like)
});

Göz bu detaylı bilgi için ya da kontrol edebilirsiniz MDN JavaScript'inizin bir dizide döngü & jQuery kontrol kullanmak için her biri için jQuery .


27

İyice underscore.js kullanmanızı öneririz kütüphanesini . Diziler / koleksiyonlar üzerinde yineleme yapmak için kullanabileceğiniz çeşitli işlevler sağlar.

Örneğin:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

7
Bu sorunun yeni keşfedicileri için , Undercore'un manevi halefi olan Lo- Dash'i birçok yönden geliştirenlere dikkat çekmek istiyorum .
Mark Reed

3
Neden kullanılmalıdır underscoreeğer ECMA-262 eklenmiştir forEachmethor. Yerel kod her zaman daha iyidir.
Walter Chapilliquen - wZVanG

27

Dizi döngüsü:

for(var i = 0; i < things.length; i++){
    var thing = things[i];
    console.log(thing);
}

Nesne döngüsü:

for(var prop in obj){
    var propValue = obj[prop];
    console.log(propValue);
}

27

Evet , bir döngü kullanarak JavaScript'te de yapabilirsiniz, ancak bununla sınırlı olmamak üzere, JavaScript'teki diziler üzerinde döngü yapmanın birçok yolu vardır. Aşağıda bu dizinin bulunduğunu ve bunun üzerinde bir döngü yapmak istediğinizi düşünün:

var arr = [1, 2, 3, 4, 5];

Bunlar çözümler:

1) Döngü için

Bir fordöngü, JavaScript'teki diziler arasında döngü oluşturmanın yaygın bir yoludur, ancak büyük diziler için en hızlı çözümler olarak kabul edilmez:

for (var i=0, l=arr.length; i<l; i++) {
  console.log(arr[i]);
}

2) Döngü sırasında

Bir while döngüsü, uzun diziler arasında geçiş yapmanın en hızlı yolu olarak kabul edilir, ancak genellikle JavaScript kodunda daha az kullanılır:

let i=0;

while (arr.length>i) {
    console.log(arr[i]);
    i++;
}

3)
A do while, whileaşağıdaki sözdizimi farklarıyla aynı şeyi yaparken yapın :

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

Bunlar JavaScript döngüleri yapmanın ana yollarıdır, ancak bunu yapmanın birkaç yolu daha vardır.

Ayrıca for inJavaScript'te nesneler arasında döngü yapmak için bir döngü kullanıyoruz .

Ayrıca bak map(), filter(), reduce()JavaScript'inizin bir Array üzerine, vb fonksiyonlar. Daha hızlı ve daha iyi kullanarak daha fazla şeyler yapabilir whileve for.

JavaScript'teki diziler üzerinden eşzamansız işlevler hakkında daha fazla bilgi edinmek istiyorsanız, bu iyi bir makaledir.

İşlevsel programlama bu günlerde geliştirme dünyasında büyük bir sıçrama yapıyor. İyi bir nedenden ötürü: İşlevsel teknikler, bir bakışta, yeniden düzenleyici ve testte anlaşılması daha kolay olan daha açıklayıcı kod yazmanıza yardımcı olabilir.

Fonksiyonel programlamanın temel taşlarından biri, listelerin ve liste işlemlerinin özel kullanımıdır. Ve bu şeyler tam olarak oldukları gibi: şeylerin dizileri ve onlara yaptığınız şeyler. Ancak fonksiyonel zihniyet onlara beklediğinizden biraz farklı davranır.

Bu makalede, "büyük üç" liste işlemleri olarak adlandırmak istediğim konulara yakından bakacağız: harita, filtre ve azaltma. Kafanızı bu üç işlevin etrafına sarmak, temiz işlevsel kod yazabilmek için önemli bir adımdır ve çok güçlü olan işlevsel ve reaktif programlama tekniklerinin kapılarını açar.

Ayrıca, bir daha asla for for döngüsü yazmak zorunda kalmayacağınız anlamına gelir.

Daha fazla >> burada :


Gerçekten bir for döngüsü ve bir while döngüsünden önce bir dizi üzerinden yineleme yaparken bir performans farkı var mı? Farklılıklar öncelikle sözdizimseldi
shea

24

Array yinelemeleri için kullanılabilen çoklu mekanizmaların performans tarafıyla ilgilenen varsa, aşağıdaki JSPerf testlerini hazırladım:

https://jsperf.com/fastest-array-iterator

Performans sonuçları

Sonuçlar:

Geleneksel for()yineleyici, özellikle dizi uzunluğu önbelleğe alındığında kullanıldığında en hızlı yöntemdir .

let arr = [1,2,3,4,5];

for(let i=0, size=arr.length; i<size; i++){
    // Do something
}

Array.prototype.forEach()Ve Array.prototype.map()yöntemler muhtemelen bir sonucu olarak, en yavaş yaklaşık değerlerdir işlev çağrısı yükü .


i = i +1yerine daha iyi kullanmaki++
DarckBlezzer

2
Geliştirilebilir: Lütfen kullanın: i ++ yerine: ++ i, bu geçici bir nesneyi önleyecektir. Böylece bellek kullanımını ve işlemci süresini azaltır (tahsis gerekmez)!
PowerStat

@ PowerStat bu konuda bir link veya referans verebilir misiniz? Bunu hiç duymadım, kulağa ilginç geliyor ...
colxi

1
@colxi Bu kadar ilginç şeyler için Herb Sutter ve Scott Meyers'ın sert C ++ içeriklerini okumalısınız. ++ i vs i ++ şey kitaptan: Olağanüstü C ++: 47 Mühendislik Bulmacalar, Programlama Sorunları ve Çözümleri - Ben de gotw.ca üzerinde bulabiliriz ama her programlama dili için kanıtlanabilir şey .
PowerStat

21

JQuery kütüphanesini kullanıyorsanız, http://api.jquery.com/jQuery.each/ adresini kullanın.

Belgelerden:

jQuery.each( collection, callback(indexInArray, valueOfElement) )

İade: Nesne

Açıklama: Hem nesneler hem de diziler üzerinde sorunsuz bir şekilde yineleme yapmak için kullanılabilen genel bir yineleyici işlevi. Length özelliğine sahip diziler ve dizi benzeri nesneler (bir işlevin argümanlar nesnesi gibi), 0'dan uzunluk-1'e kadar sayısal dizinle yinelenir. Diğer nesneler adlandırılmış özellikleriyle yinelenir.

$.each()İşlev ile aynı değildir $(selector).each()bir jQuery nesnenin üzerine, özel olarak, yineleme için kullanılan,. $.each() İşlev, bir harita (JavaScript nesne) veya bir dizi olup, herhangi bir toplama yineleme kullanılabilir. Bir dizi durumunda, geri arama her seferinde bir dizi indeksi ve karşılık gelen bir dizi değeri geçirilir. (Bu değere thisanahtar sözcükle de erişilebilir , ancak Javascript, thisdeğeri Objectbasit bir dize veya sayı değeri olsa bile her zaman bir değer olarak sarar .) Yöntem, ilk bağımsız değişkenini (yinelenen nesne) döndürür.


9
Her şey için jQuery?
İstisna

6
İstisna ile anlaştı. Ekstra bağımlılıkların etkisini hafife almayın. Zaten zaten zaten jQuery kullanarak kod dışında kod karşı bu tavsiye ederim.
Stijn de Witt

2
Güncelleme: Bu günlerde, yerel dizilerle aynı etkinin çoğunu almak için Array.forEach kullanabilirsiniz .
Stijn de Witt

20

Ben şahsen en çok sevdiğim bu varyasyonu henüz görmedim:

Bir dizi verildi:

var someArray = ["some", "example", "array"];

Length özelliğine hiç erişmeden üzerinde döngü yapabilirsiniz:

for (var i=0, item; item=someArray[i]; i++) {
  // item is "some", then "example", then "array"
  // i is the index of item in the array
  alert("someArray[" + i + "]: " + item);
}

Bunu gösteren şu JsFiddle'a bakın: http://jsfiddle.net/prvzk/

Bu yalnızca seyrek olmayan diziler için geçerlidir . Yani dizideki her dizinde bir değer vardır. Ancak, pratikte JavaScript'te seyrek diziler kullandığımı fark ettim ... Bu gibi durumlarda bir nesneyi harita / karma olarak kullanmak genellikle çok daha kolaydır. Seyrek bir diziniz varsa ve 0'ın üzerinde döngü yapmak istiyorsanız .. uzunluk-1, for (var i = 0; i <someArray.length; ++ i) yapısına ihtiyacınız vardır, ancak yine de birif de döngünün içinde var geçerli dizindeki öğenin gerçekten tanımlanıp tanımlanmadığını kontrol etmek için.

Ayrıca, aşağıdaki yorumda CMS'den bahsedildiği gibi, bunu yalnızca herhangi bir falsish değeri içermeyen dizilerde kullanabilirsiniz. Örnekteki dizeler dizisi çalışır, ancak boş dizeleriniz veya 0 veya NaN vb. Olan numaralarınız varsa döngü erkenden kesilir. Yine pratikte bu benim için neredeyse hiç bir sorun değil, ama bunu kullanmadan önce düşünmek için bir döngü haline getiren akılda tutulması gereken bir şey ... Bazı insanlar için diskalifiye edebilir :)

Bu döngü hakkında ne gibi:

  • Yazmak kısa
  • Length özelliğine erişmenize gerek yok (önbellekte sakla)
  • Erişilecek öğe, döngü gövdesinde seçtiğiniz adın altında otomatik olarak tanımlanır.
  • Listeler / yığınlar gibi diziler kullanmak için array.push ve array.splice ile çok doğal bir şekilde birleşir

Bunun çalışmasının nedeni, dizi belirtiminin, bir dizinden> = dizinin uzunluğunu okuduğunuzda, tanımsız olarak döndürülmesini zorunlu kılmasıdır. Böyle bir konuma yazdığınızda, aslında uzunluğu güncelleyecektir.

Benim için, bu yapı en çok sevdiğim Java 5 sözdizimini taklit eder:

for (String item : someArray) {
}

... döngü içindeki mevcut endeksi de bilmenin faydası


13
Bu yaklaşım ile döngü kısa sürede duracağını Bildirimi o bulur Falsey değeri böyle boş bir dize olarak, 0, false, NaN, nullveya undefined, önce bile iulaşır uzunluğu örn: jsfiddle.net/prvzk/1
CMS

3
Döngü koşulu olabilir (item=someArray[i]) !== undefined.
daniel1426

18

Prototipin özelliklerini içermeyen yalnızca kendi nesne özellikleri üzerinde yineleme yapmak için bir yöntem vardır:

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

ancak yine de özel tanımlı özellikler üzerinde yinelenecektir.

JavaScript'te, dizi de dahil olmak üzere herhangi bir nesneye herhangi bir özel özellik atanabilir.

Biri seyrek dizi üzerinden yineleme yapmak istiyorsa for (var i = 0; i < array.length; i++) if (i in array)veya array.forEachile es5shimkullanılmalıdır.


Peki kullanmaya ne dersiniz for (var i in array) if (++i)?
Daniel Sokolowski

15

JavaScript ile yapmanın birkaç yolu vardır. İlk iki örnek JavaScript örnekleridir. Üçüncüsü bir JavaScript kitaplığını kullanır, yani jQuery .each()işlevi kullanır.

var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
  alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


for...inbenzeri nesneler için kaçınılmalıdır
brk

15

En zarif ve hızlı yol

var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}

http://jsperf.com/native-loop-performance/8


Düzenlendi (çünkü yanılmışım)


100000 öğeden oluşan bir dizi arasında döngü yapma yöntemlerini karşılaştırma ve her seferinde yeni değerle minimum işlem yapma.

Hazırlık:

<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        // Fake function with minimal action on the value
        var tmp = 0;
        var process = function(value) {
            tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
        };

        // Declare the test Array
        var arr = [];
        for (var i = 0; i < 100000; i++)
            arr[i] = i;
    };
</script>

Testler:

<a href="http://jsperf.com/native-loop-performance/16" 
   title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>

Bu döngü dizideki öğelerin sırasını izlemiyor gibi görünüyor.
Deniz Ozger

Testim yanlıştı. Doğru, şimdi tüm DÖNGÜLERİ gösteriyor. jsperf.com/native-loop-performance/16
molokoloco

@bergi haklı. Bu döngü diziyi içinden geçerken siler. Çoğu durumda ne istediğinizi değil.
Stijn de Witt

4
falsey eşyalarını kırıyor.
njzk2

12

Optimize edilmiş yaklaşım, dizinin uzunluğunu önbelleğe almak ve tüm değişkenleri tek var anahtar kelimeyle başlatan tek değişken modeli kullanmaktır.

var i, max, myStringArray = ["Hello","World"];
for (i = 0, max = myStringArray.length; i < max; i++) {
    alert(myStringArray[i]);
   //Do something
}

Yineleme sırası ters çevrimi denemenizden önemli değilse, genel durum testini azalttığı ve azaltmanın tek bir ifadede olduğu için en hızlısıdır:

var i,myStringArray = ["item1","item2"];
for (i =  myStringArray.length; i--) {
    alert(myStringArray[i]);
}

veya döngü sırasında kullanmak için daha iyi ve daha temiz:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // do something with fruits[i]
}

12

JavaScript'te, bir diziyi döngüye almak için çok fazla çözüm vardır.

Aşağıdaki kod popüler olanlardır

/** Declare inputs */
const items = ['Hello', 'World']

/** Solution 1. Simple for */
console.log('solution 1. simple for')

for (let i = 0; i < items.length; i++) {
  console.log(items[i])
}

console.log()
console.log()

/** Solution 2. Simple while */
console.log('solution 2. simple while')

let i = 0
while (i < items.length) {
  console.log(items[i++])
}

console.log()
console.log()

/** Solution 3. forEach*/
console.log('solution 3. forEach')

items.forEach(item => {
  console.log(item)
})

console.log()
console.log()

/** Solution 4. for-of*/
console.log('solution 4. for-of')

for (const item of items) {
  console.log(item)
}

console.log()
console.log()


12

JQuery kullanmak istiyorsanız, belgelerinde güzel bir örnek vardır:

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });

12

Bence en iyi yol Array.forEach işlevini kullanmaktır. Bunu kullanamıyorsanız, MDN'den çoklu dolgu almanızı öneririm. Kullanılabilir hale getirmek için, JavaScript'teki bir dizi üzerinde yineleme yapmanın kesinlikle en güvenli yoludur.

Array.prototype.forEach ()

Diğerlerinin önerdiği gibi, bu neredeyse her zaman istediğiniz şeydir:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

Bu, diziyi işlemek için ihtiyacınız olan her şeyin bu kapsam dahilinde kalmasını ve nesne özelliklerinin ve diğer üyelerin değil, yalnızca dizinin değerlerini işlemenizi sağlar for ...

forÇoğu durumda normal bir C stili döngü kullanmak işe yarar. Döngü içindeki her şeyin kapsamını programınızın geri kalanıyla paylaştığını hatırlamak önemlidir, {} yeni bir kapsam oluşturmaz.

Dolayısıyla:

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

for(var i = 0; i<numbers.length; ++i){
  sum += numbers[i];
}

alert(i);

"11" çıktısını verir - bu, istediğiniz gibi olabilir veya olmayabilir.

Çalışan bir jsFiddle örneği: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/


10

% 100 özdeş değil, benzer:

   var myStringArray = ['Hello', 'World']; // array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }


1
Bu, bir dizi nesnesiyle kullanımlarda olduğu gibi benzer sorunlara karşı çalışacak gibi görünüyor, ki prototip üye değişkenleri de for tarafından yakalanacaktı.
Kzqai

9

Örneğin, bir Firefox konsolunda kullandım:

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})

9
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

Çok daha temiz ...


Buna göre çok temiz değil z.forEach(j => console.log(j));.
Sapphire_Brick

9

Kısa cevap: evet. Bununla yapabilirsiniz:

var myArray = ["element1", "element2", "element3", "element4"];

for (i = 0; i < myArray.length; i++) {
  console.log(myArray[i]);
}

Bir tarayıcı konsolunda "element1", "element2" vb. Gibi bir şeyin basılı olduğunu görebilirsiniz.


9

Şunlardan birini kullanabilirsiniz Array.prototype.forEach(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach((item, index)=>{
   //Some code...
});

Veya Array.prototype.map(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.map((item, index)=>{
   //Some code...
});

Veya jquery veya daha önce bahsedilen döngü yolları için.

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.