JavaScript Temelleri

Bölüm 2

Temel Bilgiler

2.13 - Döngüler (Devam)

Bölüm 2 Sayfa 16

2.13.4 - do ... while Döngüleri

do...while döngülerinin sözyazımı aşağıdaki gibidir:

do
Bildirim
while (Kontrol İfadesi)
		

Bildirimler birden fazla olursa, blok parantezleri arasına alınır.

do...while Döngüleri ters çevrilmiş whiledöngüleridir. Döngü tekrarlama kontrolü döngünün sonunda yapıldığı için, program kontrolü en az bir kez bu döngünün içinde girer yani iterasyon en az bir kez gerçekleşmek zorundadır.

do...while Döngüleri fazla kullanılmaz, bunun nedeni bir yandan döngünün en az bir kex gerçekleşmek zorunda olması ve diğer döngülerin bu döngünün işlevini yapabilmeleridir. Bu döngülerin kullanıldığı bir uygulamanın JavaScript kodları aşağıda görülmektedir.

var toplam = 0 , i = 10 , s = 0;
			
do {
			
toplam += i;
i--;
s++;
			
}while(i >0);

		

Bu programın sonucu:

2.13.5 - for...in Döngüleri

for..in Döngüleri çok ilginçtir çünkü bu döngü yapılanması klasik bir döngü değildir. Bu döngüler nesne örneklerinin sayılabilir (enumerable) özelliklerini bir döngü iterasyonun eşdeğer şekilde tarayayabilirler.

for..in Döngülerinin sözdizimi aşağıdaki gibidir :

for(anahtar in nesne örneği)
Bildirim
		

Bildirimler birden fazla olursa, blok parantezleri içine alınır. Bu çok basit yazılımın kullanımı da çok basittir. Döngü işlemleri, JavaScript yorumlayıcısı tarafından kullanıcıya belli etmeden gerçekleştirilir. Sadece sonuçlar kullanıcıya aktarılır. Sözdiziminde anahtar olarak belirtilen değer kullanıcı tarafından istendiği gibi seçilebilen bir tanımlayıcı (identifier) olabilir ve istendiğinde for(var anahtar ... şeklinde, döngü ile birlikte tanıtılabilir. Bu anahtara, her iterasyonda bir nesne özelliği otomatik olarak kullanıcı farketmeden atanır. Tüm iterasyon boyunca, anahtar bu özelliğin bir benzeri (alias) haline gelir. Tüm iterasyon boyunca bu özelliğin değerine, anahtar aracılığı ile ulaşılır, bir sonraki iterasyonda aynı anahtara başka bir özellik atanır ve döngü, nesnenin tüm özellikleri tarandıktan sonra tamamlanır.

for..in Döngülerinde, değişkene atanabilecek özelliklerin sayılabilir (enumerable) olması gerekir. Öntanımlı nesnelerin öntanımlı metotları ve öntanımlı özellikleri sayılabilir değildir. Buna karşılık, tüm kullanıcı tanımlı nesnelerin kullanıcı tanımlı özellik ve metotları sayılabilir niteliktedir.

Henüz nesnelerle geniş ölçüde çalışmamış olmamıza karşın, nesnelerle çalışma 2.6.1 bölümünde açıklanmıştı. Burada, bu bilgilerden yararlanıp bir nesne literali yaratacak ve özelliklerini for..in döngülerinden yararlanarak inceleyeceğiz. Nesne özellikleri, hem statik hem de dinamik özellikleri (metotları) kapsar. Pratikte özellik olarak statik özellikler düşünülür. Aslında özellik terimi, bir nesnenin metotları dahil tüm özelliklerini kapsar. Bu nedenle, for..in döngüleri sayılabilir metotlar dahil tüm sayılabilir özelliklerin dökümünü verir. Tüm öntanımlı nesne sınıflarının öntanımlı özellik ve metotları, öntanımlı olarak sayılamaz nitelike olduklarından, öntanımlı nesne sınıflarının örneklerinin özellikleri, for..in döngüleri ile tarandığında , öntanımlı özellik ve metotlar listede görülmezler. Aşağıda, JavaScript kodları verilmiş olan uygulama, bir kullanıcı tanımlı nesne örneğinin (aslında bir nesne literali) özelliklerinin for..in döngüleri yardımı ile incelenmesini açıklamaktadır:

function forinDöngüsü() {

var i;
var birParmakBoru = {
çap : 2.54 ,
etKalınlığı : 2 ,
dışKesit : function() {
var dışÇap = this.etkalınlığı * 2 + this.çap;
return dışÇap * dışÇap * Math.PI / 4;
}

for(nesneÖzelliği in birParmakBoru) {

bilgiYaz('Özellik ' + i + ' - ' + nesneÖzelliği + ' : ' + birParmakBoru[nesneÖzelliği] + '       ', 'b2.13.5-uyg-1-sonuç-1');

}
		

Bu programın sonucu:

Yukarıdaki programın çıktısı, fazla çarpıcı olmamasına karşın, nesne özelliklerinin adları ve değerleri üzerinde okunabilir bir bilgi sağlamaktadır. Bu program evrenseldir ve her türlü nesne örneğine uygulanabilir. Daha gözalıcı çıktılar için ileride dizi verilerinin çıktıları için uygulanacağı gibi, dizi yazılımı ve Belge Nesne Modeli (DOM) bilgilerinin kullanılması gerekecektir.

Nesne özelliklerinin for..in döngüleri ile görüntülenmesinde, özelliklerin taranma sırasının önceden belli olmayabileceği belirtilmesine karşın, uygulamalarımızda dizilerin eleman sırası ile, nesne özelliklerinin de tanım sırası ile görüntülendiği görülmektedir.

İleride inceleyeceğimiz dizi sınıfı nesne örnekleri veya kısa adıyla dizi elemanlarının for..in döngüleri ile görüntülenmelerinde dikate alınması gereken konu, dizi nesne örneklerine kullanıcı tanımlı katkıların sayılabilir nitelikte olmaları ve dizi elemanları ile birlikte görüntülenecek olmalarıdır. Bunun dışında dizilerin kopyalanmasında for..in döngülerinin tek uygulanması gereken otomatizasyon yöntemi olmasıdır. Bunun nedeni aşağıda açıklanmaktadır.

Diziler bir nesne sınıfı olmalarına karşın, dizi sınıfı nesne örnekleri yani diziler ile generik nesne sınıfı örnekleri (nesne literalleri, kullanıcı tanımlı nesne sınıfı örnekleri veya Object sınıfı örnekleri) birbirinden farklıdır. Nesne özelliklerine hem nokta, hem de []işlemcileri ile erişilebilmesine karşın, dizi elemanlarına sadece [] işlemcisi ile erişilebilir. Dizilerde nokta işlemcisi sadece dizi nesne örneğine yapılmış kullanıcı tanımlı özelliklerin erişiminde kullanılabilir.

Diziler referansla aktarılan veri tipleridir ve bağımsız kopyalarının alınabilmesi için, elemanlarının teker teker yeni bir değişkene kopyalanması gerekir. Bu kopyalama for, while, do..while gibi döngüler kullanılarak yapılırsa sadece elemanların güncel değerleri kopyalanmış olur. Kopyalamanın tam olması için, kullanıcı tanımlı nesne örneği özellklerinin de yeni değişkene elle tanıtılması gerekir. Bu da otomatizayon değildir. Bunun yerine kopyalama for..in döngüleri ile gerçekleştirilirse, hiç elle müdahaleye gerek kalmadan tüm kopyalama gerçekleşmiş olur. Dizilerin kopyalanması için sorunsuz olarak kullanılabilecek bir alt program bdelib.js program kitaplığına eklenmiştir. Bu alt programın kullanılışı,

diziKopyala(orijinalDizi, kopyaDizi);
		

şeklindedir.

2.13.6 - break Bildirimi

Bir döngü bildirimleri arasında break bildirimi, bir sonraki bildirimin çalıştırılmayıp, kontrolün döngü dışındaki ilk bildirime aktarılmasına neden olur. Bu işleme döngünün kırılması adı da verilir.

Bazı durumlarda, içiçe döngüler çalıştırılır. Bu döngülerin en içinden en dış döngünün dışına aktarılma için, etiketli bloklar kullanılabilir. Blok etiketlerinin adları, değişken adlarından bağımsızdır. Aynı adla bir değişken ve bir blok etiketinin olması isim çakışmasına neden olmaz. Bir etiketli blok uygulamasının JavaScript kodları aşağıda görülmektedir:

...
var kontrol = 16;
va : 
for(var i = 0; i < 100; i++) {
for(var j = 0; j< 10; j++) {
kontrol = i * j;
if (kontrol > 800) {
break va;
}
}

bilgiYaz('kontrol =' + kontrol, 'b2.13.6-uyg-1-sonuç-1');
...
		

Bu programın sonucu:

olmaktadır. Bu şekilde en iç döngüde bildirilen break bildirimi, tüm döngü sisteminin kırılması ile önceden çıkış (prematüre çıkış) sağlamaktadır.

Program yazımında, break bildirimi yanında bir etiketle birlikte kullanılcaksa, her ikisi de aynı satırda olmalıdır. Satır atlanırsa, JavaScript yorumlayıcısı satır sonunda bir bildirim sonlandırıcısı (;) varmış gibi hareket eder ve break bildirimi ile etiketinin ilgisini keser, etiket alt satırda bağlantısız kalır ve program hata verir. Bu yüzden break bildirimi ile etiketi aynı satırda yazılmalıdır.

JavaScript blokları ek bir kapsam alanı sağlamaz. Sadece fonksiyonların kapsam alanları vardır. Bloklar etiketlenebilir fakat içiçe döngülerden başka bloklar için bu bir anlam taşımaz. Tek bir bir döngü bloğundan olgunlaşmadan çıkış için bloğun etiketlenmesi gerekmez. Çünkü tek bir döngü bloğunda sadece break bildirimi, prematüre çıkış sağlayabilir. Etiketleme sadece içiçe döngü bloklarının kırılması için gereklidir. Başka durumlarda kullanımı yoktur. Bunun işlevsiz olmasının nedeni, JavaScript programlama dilinin, sadece mantıksal program dallanmasını desteklemesidir. JavaScript programlama dilinde, goto gibi bildirimlerle, program akış kontrolü etiketli bloklara yönlendirilemez. Yani mantıksal olmayan akış kontrolü yoktur.

2.13.7 - continue Bildirimi

continue Bildirimi bir iterasyonu atlatır ve bir sonraki iterasyonla devam edilir. Bu bildirimin sözdizimi,

continue [etiket]
		

şeklindedir. İsteğe bağlı olarak etiketli olarak olarak da kullanılabilir. Bu ikisi aynı satırda olmalıdır. Bu bildirim sadece döngülerin gövdesinde kullanılabilir. Başka yerde kullanılırsa JavaScript yorumlayıcısı hata verir.

Bir iterasyonda, continue bilidirimine rastlanıncaya kadar, çalıştırılabilecek tüm bildirimler çalıştırılır. for Döngülerinde, continue bildiriminden sonra, iterasyonda geri kalan terimler çalıştırılmaz, kontrol döngü başına atlar, otomatik sayaç arttırımı gerçekleşir, döngü kontrolü sınanır, henüz gerçek ise, döngünün geri kalan iterasyonlarına devam edilir. Aşağıda JavaScript kodları verilmiş olan uygulamada, içiçe iki döngünün en içtekine bir koşullu continue bildirimi konulmuştur. Bu koşul gerçekleşince itersayon kesilerek bir sonrakine geçilmektedir. İç döngünün tasarımı, continue bildiriminden sonra, çalıştırılacak bir bildirim olacak şekilde yapılmıştır. Yani, bir iterasyon atlanırsa, sonuç bundan etkilenecektir. Uygulama sonuçları aşağıda görülmektedir.


var kontrol = 16;

va : 
for (var i = 0; i < 3; i++) {
for (var j = 0; j< 3; j++) {
if (j === 1) {
continue;
}
kontrol = kontrol + i * j;
}
}

bilgiYaz('kontrol =' + kontrol, 'b2.13.7-uyg-1-sonuç-1');
		

Bu programın sonucu:

Bu programda, en iç döngünün döngü sayacının 1 olduğu iterasyondaki, kontrol değişkeni ataması atlanmaktadır. Bu durumda, kontrol değişkeninin değerinin değişimi aşağıdaki sıraya göre gerçekleşir :

i = 0 ( j = 0, 2)

 
kontrol = 16 + 0  * 0 + 0  * 2
		

i = 1 ( j = 0, 2)

kontrol = 16 + 1  * 0 + 1  * 2
		

i = 2 ( j = 0, 2)

kontrol = 18 + 2  * 0 + 2  * 2
		

Sonuç :

kontrol = 22
		

Su son uygulamada, continue bildirimi, dış döngünün etiketi ile birlikte kullanılırsa, dış döngüde ikinci iterasyon atlatılır. Bu durumda, programda kontrol değişkeninin ulaşacağı değer de değişik olur. Aşağıda JavaScript kodları verilmiş olan uygulamada bu yöntem incelenmiştir.


var kontrol = 16;

va : 
for (var i = 0; i < 3; i++) {
for (var j = 0; j< 3; j++) {
if (j === 1) {
continue va;
}
kontrol = kontrol + i * j;
}
}

bilgiYaz('kontrol =' + kontrol, 'b2.13.7-uyg-2-sonuç-1');
		

Bu programın sonucu:

Burada, i = 0 olduğunda, j = 0 olmakta, j =1 olduğunda if den sonraki bildirimler çalıştırılmadan i = 1 olmakta burada j = 0 normal çalışmakta, j = 1 olunca i = 2 olmakta ve j = dan sonra döngüden çıkılmaktadır. Burada, kontrol değişkeninin değerini değiştirebilecek terimler,

kontrol = 16 + 0 * 0 + 1 * 0 + 2 * 0
		

olmakta ve sonuçta kontrol değişkeninin değeri değişmemektedir.

Sadece bir düzeyli döngülerin etiketlenmesine gerek yoktur. Bu döngülerde,

ATA : 
for (var i = 0; i<10; i++ ) {
if (i === 4) {
continue ATA;
}
hedef = a + i - b * j;
}
		

döngüsü ile,

for (var i = 0; i<10; i++ ) {
if (i === 4) {
continue ;
}
hedef = a + i - b * j;
}
		

döngüsü arasında bir fark yoktur. Her iki döngüden sonra da hedef değişkenin değeri aynı olacaktır.

while Döngülerinde, continue bildiriminin kulanımında çok dikkatli olmak gerekir, çünkü while döngülerinde otomatik sayaç arttırımı yoktur ve continue bildiriminden sonra, kontrol iterasyonun geri kalan bildirimlerini atlayarak yeniden, döngü başındaki kontrol ifadesine geri döner. Bu ifade henüz true değerini veriyorsa, yeni bir iterasyona başlatılır. Eğer sayaç arttırımı, continue bildiriminden sonra ise, döngü sayacı aynı kalacağı için sonsuz döngüye girilir. Aşağıda bu durumu açıklayan bir program görülmektedir :

i = 0;
while (i < 3 ) {
Bildirim 1;
if (i === 1) {
continue ;
}
Bildirim 2;
i++;
Bildirim 3;
}
		
		

Bu programda, ilk iterasyon tamamlanır ve i sayacının değeri bir artarak 1 değerini alır. Bu iterasyonda, if kontrolu gerçek olur ve bu terimden sonraki tüm bildirimler atlanarak kontrol döngü başı kontrolüne döner. Döngü sayacının arttırılması ifadesi de atlanmış olduğundan, döngü sayacının değeri arttırılamadan iterasyondan prematüre olarak çıkılmıştır. Yeniden döngü başı kontrolüne dönülür ve bir önceki iterasyondaki döngü sayacının değeri olan 1 değişmemiş olarak kalmış olduğundan, döngü başı kontrolünün sonucu aynı bir önceki iterasyon gibi gerçek olarak değerlenir. Bu durumda, Yeni bir iterasyon başlatılır ve yine if kontrolu gerçek olur yine sayaç değeri 1 olarak başa dönülür ve bu sonsuza kadar devam eder. Bunun için, while döngülerine hiç değilse program rayına oturana kadar, aşağıda görüldüğü gibi bir iterasyon üst sınırı konulmalıdır. Sonsuz döngüye girilmesinin önlenmesi için, sayaç arttırımı, continue bildiriminden önce gerçekleştirilmelidir. Aşağıda continue bildirimi içeren güvenli bir while döngüsü örneğinin, JavaScript programının kodları görülmektedir.

var i = 0, q =0, toplam = 0;
while (i < 3 && q <10000) {
i++;
q++;
if (i === 1) {
continue ;
}
toplam += i;
}
bilgiYaz('toplam =' + toplam, 'b2.13.7-uyg-3-sonuç-1');
		

Bu programın sonucu:

olamaktadır. Yukarıdaki programda, döngü sayaç kontrolü, JavaScript kodları aşağıda görülmekte olan, uygulama gibi, if bildiriminin altında olursa, while döngüsünden çıkışı kontrol eden mantıksal ifadenin sol işleneni işlevsiz kalacak ve döngü çıkışını sadece güvenlik sınırı sağlayabilecektir.

var i = 0, q =0, toplam = 0;
while (i < 3 && q <10000) {
q++;
if (i === 1) {
continue ;
}

i++;
toplam += i;
}
bilgiYaz('Gerçekleşen İterasyon Sayısı =' + q, 'b2.13.7-uyg-4-sonuç-1');
		

Bu programın sonucu:

olmaktadır. Gerçekten, döngü sayaç sınırlaması için, güvenlik değişkeni q konulmasa, program sonsuz döngüye girmiş olacaktı. Güvenlik sınırı bunu önlemiştir.

JavaScript 1.2 sürümü, continue bildirimi içeren do...while döngüleri için hatalı sonuç verdiğinden, do...while döngüleri continue bildirimi içerecekse, bu döngülerin kullanılmasından vazgeçilip, eşdeğer for döngülerininin kullanılması sağlık verilmektedir.

for ...in Döngülerinde continue bildirimi, bir sonraki özelliğe atlanması sonucunu doğuracaktır.

Valid XHTML 1.1