Javascript Yazılım Kuralları (JS)

22 Aralık 2007

Denetim Yapıları

if deyimi

if( myVariable == 2 ) {
  myVariable = 1;
} else {
  myVariable = 0;
}
Eğer myvariable 2 olsaydı, işlemden sonra 1 olurdu. Eğer 2'den başka birşey olsaydı işlem sonrası değeri 0 olurdu.

Eğer deyimi, bir nesnenin olmayan çocuk nesnesinin varlığını da test edebilir. Örneğin bazı tarayıcılar document.body.style nesnesini sunarken eski tarayıcılar document.body nesnesini sunmaz bile. Bunları kullanırken document.body.style hata verir. Sorunu çözmek için:
if( document.body ) {
  if( document.body.style ) { vb. }
}

Burada && işlemiyle daha kullanışlı bir "if" deyimi yapılabilir:
if( document.body && document.body.style ) { vb. }

Eğer ilk karşılaştırma yanlışsa, ikinciye devam edilmez. Buna kısa devre de denir. Aynı biçimde || işlemi de kullanılabilir. Ama bu işlemde ikinci koşul birincisi yanlış olsa da irdelenir.

Eğer kıvrımlı parantezler olmazsa if deyiminden sonraki yalnız deyim "if" deyiminin parçası olur.
if( x < 5 )
x++;
window.alert(x);

Bu örnekte "alert" x değerine bakmaksızın oluşur ama x değeri ancak 5'den küçükse bir arttırılır. Bu kural, kullanılır bir özellik gibi gözükebilir. Çünkü kodlamanızı biraz daha küçültmüş olursunuz ama, önerilen bu yazım kurallını hiç kullanmamanızdır. Eğer denetim yapılarını iç içe kullanmaya başlarsanız, kodlamanızın okunması çok güçleşir. Her zaman kıvrımlı parantez kullanmak (seçenek olsa bile) daha iyidir.

Aşağıdaki gibi iç içe tanımlanmış "if" deyimlerinde yönetim güçleşmeye başlar:
if( myVariable == 2 ) {
  myVariable = 1;
} else {
  if( myVariable == 5 ) {
    myVariable = 3;
  } else {
    myVariable = 4;
  }
}

Başka programlama dillerinde olduğu gibi kıvrımlı parantezler kullanışlı bir biçimde kaldırılabilir. Burada "elseif" değil "else if" kullanıldığına dikkat edilmelidir.
if( myVariable == 2 ) {
  myVariable = 1;
} else if( myVariable == 5 ) {
  myVariable = 3;
} else {
  myVariable = 4;
}

'for' Döngüsü


En sık kullanılan yapılardan biridir. Bir dizinin içeriğinde gezinirken kullanılır (tipik kullanım biçimlerinden biridir). Ya da belirli sayıda nesne yaratırken önemli olur. 'for' döngüsünün yazım kuralı şöyledir:
for( ilk_değer; gidebildiğin_kadar_koşulu; her_zaman_yap )

ilk_değer
Döngü içinde kullanılan yeni değişkenlerin tanımladığı yerdir. Özellikle arttırılan sayaçlar burada tanımlanır. Her değişkende olduğu gibi bu değişkenlerin de tanımı yapılmalıdır. Birden çok değişkeni aşağıdaki gibi tanımlamak olanağı vardır (eğer gerek varsa):
    var degisken1 = deger, degisken2 = baska_deger;
Bu değişkenler 'for' döngüsü içinde kalmakla sınırlı değildirler. Döngüyle aynı kapsam içinde olan tüm kodlamada kullanılabilirler.
gidebildiğin_kadar_koşulu
Hangi koşulda döngü deyimlerinin çalıştırılacağının belirtildiği yerdir. Döngüye devam etme koşulu burada belirtilir. Koşulda && ya da || kullanılabilir.
    degisken1 <= 5 && degisken2 >= 70;
Eğer koşul sağlanmazsa kodlama döngüye hiç girmez.
her_zaman_yap
Bir kez döngünün sonuna gelinince, burada ne yapılacağı belirtilir. Tipik olarak döngü değişkenlerinin değerleri arttırılır ya da eksiltilir. Birden çok işlem için aralarına virgül koymak gerekir.
    degisken1++, degisken2 -= 4

Aşağıdaki tam bir örnektir:
for( var degisken = 1; degisken <= 5; degisken++ ) {
  myArray[degisken] = 1;
}
burada myArray[1]'den myArray[5]'e kadar hepsi 1 olur.

'for - in' Döngüsü

Bu döngü bir nesnenin tüm özellikleri ya da bir dizinin tüm öğeleri için kullanılır. Döngü öğeler bitince son bulur. Her yeni öğe ya da özellik eklendiğinde açılıp sergilenen öğelere eklenmiş olurlar. Tüm iç öğeler de (javascript tarafından üretilenler dahil) açılıp sergilenir. Ama Javascript yorumlayıcısı kendi eklediklerini gizler. Burada özel durumlarla pek ilgilenmemek gerekir. Çünkü tarayıcılara bağımlı olarak gizlenen ya da açılan iç öğeler farklılık gösterir.

Burada da kullandığınız değişken adlarını tanımlamanız gerekir. "for in" döngüsü yazım kuralı şöyledir:
for( var degisken in Nesne_yada_Dizi ) {

Sergilenen her Nesne_yada_Dizi özelliği için döngü bir kez tamamlanır. Bir sonraki özellik desikene atanır. Bu özelliğe erişmek için dizi yazım kuralı kullanılabilir. Aşağıdaki örnek sergilenen özellikleri yazar:
for( var degisken in document ) {
  document.write( degisken + ' = ' + document[degisken] + '
' ); }

Eğer bu döngüyü bir dizide kullanırsanız sayılanmış ve adlanmış öğeleri listeler hatta iç kullanımla ilgili length (uzunluk) özelliğini de gösterir. Kullanımda sorun olmaması için özen gösterilmelidir.

'while' Döngüsü


'while' döngüsü 'for' döngüsüne benzer. Fark ilk değerlerle, döngü sonu işlemlerindedir. Döngü koşulu doğru olduğu sürece devam eder.
var deger = 1;

while( deger <= 5 ) {
  myArray[deger] = 1;
  deger++;
}
myArray[1]'dan myArray[5]'e kadar hepsi 1 olur.

Burada arttırma ya da eksiltme işlemini kullanıp kodlamayı 'myArray[degisken++] = 1;' yazarak kısaltabilirsiniz. Burada önce "degisken" dizinin öğesini işaretler sonra değeri arttırılır.

Bunun tersi de çalışır: 'myArray[++degisken] = 1;'. Burada önce degiskenin değeri arttırılır sonra yeni değer dizinin hücresini işaretler.

Bu özellikler döngü dışında da çalışır. Ama daha çok döngü içinde kullanılır.

'do - while' Döngüsü



Bu da aynı "while" döngüsü gibidir ama çok önemli bir farkla. Koşul döngünün sonunda hesaplanır. Bu nedenle döngü en az bir kez çalışır.
var degisken = 1;

do {
  myArray[degisken] = 1;
  degisken++;
} while( degisken <= 5 );
myArray[1]'den myArray[5]'e kadar 1 olur.

'switch' Deyimi


"switch" yinelenmiş "if" deyimi gibidir. Burada degiskenin değeri listelenenlerden hangisine uyarsa o deyimler çalıştırılır.
switch(degisken) {
  case 1:
    //Eğer degisken 1 ise çalıştırılır
  case 'sample':
    //Eğer degisken 'sample' (ya da 1, nedeni aşağıda anlatıldı) ise
    //burası çalıştırılır
  case false:
    //Eğer degisken false (ya da 1 ya da 'sample', aşağıdaki paragrafa bakın)
    //burası çalıştırılır
  default:
    //Eğer değişken hiç birine uymuyorsa (ya da 1 ise
    //ya da 'sample' ya da false, alttaki paragrafa bakın)
    //burası çalıştırılır
}

Eğer "case" uyumluysa onun altındaki kod çalıştırılır "break" deyimi kullanılmazsa altındaki kodlar da çalıştırılır. Buna karşın çözüm: "break" deyimi kullanmaktır.
switch(değişken) {
  case 1:
    //Eğer degisken 1 ise çalıştırılır
    break;
  case 'sample':
    //Eğer degisken 'sample' ise çalıştırılır
    break;
  case false:
    //Eğer degisken false ise çalıştırılır
    break;
  default:
    //Eğer degisken hiçbirine uymazsa burası çalıştırılır
    //break; burada gereksizdir, izleyen deyim ya da koşul yok...
}

'with' Deyimi


Aşağıdaki örneğe bakın:
x = Math.round( Math.LN2 + Math.E + Math.pow( y, 4 ) );
'with' deyimi kullanılarak aşağıdaki gibi kodlanabilir:
with( Math ) {
  x = round( LN2 + E + pow( y, 4 ) );
}

'with' deyimi fazladan değişken adlarını o anki kapsam içine alır. Eğer daha önce pow adlı bir değişkeniniz varsa bu değişken 'with' deyimi içinde geçerli değildir. Çünkü aynı adlı Math yöntemiyle değişmiştir. Bir kez with deyimi kapandı mı, eski değişken yeniden kullanılabilir.

Çabuk 'if' deyimi


Buna koşullu atama işlemi de denir. Değişik değerleri koşullara göre bir değişkene atama işlemidir.
var myVariable = document.getElementById ? 1 : 0;
Bununla aşağıdaki özdeştir:
if( document.getElementById ) {
  var myVariable = 1;
} else {
  var myVariable = 0;
}

try - catch - finally deyimi

  • Netscape 4, Internet Explorer 4 ve WebTV bu yapıyı desteklemez ve hata verir.

  • 'try - catch - finally' denetim yapısı hataları yakalarken hata mesajı oluşturmadan ya da kodlamayı kesmeden sessizce denetimi tamamlanamaktır. Aslında işlemleri akan kodlamayı da kesmeye gerek olmaz.
    window.onerror = referenceToFunction;
    
    'try - catch - finally' denetim yapısının yazım kuralları şöyledir:
    try {
      //buarda hata veren bir deyim olsun 
    } catch( myError ) {
      //Eğer hata olursa, bu kodlama çalışır
      //nesnedeki iki özellik (varsayılan olarak) deyime geçer
      alert( myError.name + ': ' + myError.message );
    } finally {
      //seçenekli - yakaladığınız hatayı yeniden oluştursanız bile
      //bu kodlama denetim yapısı bitmeden çalışır
    }
    
    Eğer 'try' bölümünde bir hata oluşursa, hatayla ilgili bilgiyi de geçirerek hemen 'catch' bölümüne geçilir. Aynı hata için değişik tarayıcılar değişik hatalar oluştururlar. Kuramda, DOM tarayıcıları belirli sınıflara ayrılmış hata mesajları oluştururlar. Ama sonuçlar DOM uyumluluk düzeylerine bağımlıdır. 'try' ve 'catch' bölümü bittikten sonra 'finally' bölümü çalışır.

    Eğer bu deyimleri iç içe kullanırsanız, hatayı içteki 'catch' bölümünden dıştaki 'catch' bölümüne taşıyabilirsiniz. Eğer varsa içteki 'finally' bölümü dıştaki 'catch' çalışmadan bitirilir ama içtekini izleyen kodlama çalıştırılmaz. Bu işlem 'throw' (fırlat) yöntemiyle gerçekleşir.
    try{
      //...Buradaya bir takım kod yazılır
      try {
        var a = nonexist.b; //Bu hata verir
      } catch(myError) {
        //Hatayı yakalar ve mesaj verir
        alert( myError.message );
        //hatayı dışarıdaki try-catch ikilisine fırlat
        throw( myError );
      }
      //...burada başka bir kod var
    } catch( myErrorObject ) {
      //Buraya fırlatılan hata düşer. Bu nedenle hata nesnesi 
      // aynıdır. O halde mesaj da aynı olur.
      alert( myErrorObject.message );
    }
    
    Kendi hatalarınızı da herhangi noktadan fırlatabilirsiniz. Hatayı gerekli özelliklerle üretir ve throw deyimine uygun parametre yaparsanız işlem tamamlanır:
    try{
      var myEr = new Object();
      myEr.name = 'My error';
      myEr.message = 'Benim istemediğim bir şey yaptınız';
      throw( myEr );
    } catch( detectedError ) {
      alert( detectedError.name + '\n' + detectedError.message );
    }
    

    Bunda hatalı olan ne?

    Eski tarayıcılar bunu desteklemez ama şükür artık kimse onları kullanıyor. Örneğin NN 4 bunu desteklemiyor. Halbuki desteklese ne çok hata oluşurdu.

    Maalesef bu yapıyı desteklemeyen bir tarayıcıda kullanılırsa tarayıcı tüm kodlamayı keser. Denetleme yapısını kullanmasa bile kodlama kesilir.

    Hiçbir zaman tarayıcının destekleyip desteklemediği araştırılan document.getElementId gibi olmayacaktır. O zaman nerede kullanılacaktır?

    W3C DOM kodlamasında kullanılabilir. Örneğin değişen DOM hatalarında kullanılabilir. Bunlar bilinen hatalardır ama size bir şeyleri nasıl yapmamanız gerektiğini söyler. Başka tarayıcılar DOM desteklemezse bu hatayla ilgilenmeleri zaten gerekmez. O halde Javascript 1.2 kullanmak gerekir (daha yükseği değil). Bunun anlamı eski tarayıcılar hala hata verebilir ama onların hata kaldırma koşulları korunmalıdır.

    Bazen sizin fırlattığınız hatalar için de kullanılır. Ama hatayı bazı koşullara uygun hazırlamak gerekir.

    "Frameset" bir "frame" için tarayıcı güvenlik hatası yaparsa kullanılabilir. Güvenlik hatası frame içeriği bir başka siteye aitse gerçekleşir).

    Eğer değişik tarayıcılar aynı deyimi değişik biçimlerde yorumladığında kullanılmalıdır. Örneğin selectBox.add yöntemi (bu yöntem DOM bölümüne bu karışıklıktan doyalı eklenmedi):
    try {
      selectBox.add(optionObject,otherOptionObject);
    } catch ( e ) {
      selectBox.add(optionObject,index);
    }
    

    Koşul olmayan koşullular

    Çabuk 'if' deyiminde olduğu gibi bazen bir özellik hiçbir değerle koşul oluşturmadan kullanılır: 'if(document.getElementId)' gibi...

    Bu geçerli bir kullanımdır. Hatta Javascript kodlamanın en kullanışlı işlemidir. En önemli kurallardan biridir. Nesne ve beceri belirleme amaçlı kullanım olduğu için tarayıcılar arası kodlamada çok anlamlıdır:
    document.getElementById != "" &&
    document.getElementById != 0 &&
    document.getElementById != false &&
    document.getElementById != undefined &&
    document.getElementById != null
    
    Tüm bu koşulların yerine: 'if( !document.getElementById )' yazılmış olunur.

    Bu kullanım doğrudur eğer:
    document.getElementById == "" ||
    document.getElementById == 0 ||
    document.getElementById == false ||
    document.getElementById == undefined ||
    document.getElementById == null
    
    doğruysa...

    Bunu kullanarak tek beceri elde edilir. Yanlışsa, başkasına bak, yoksa aranan bulunmuştur...

    Bunu koşul gerektiren her yerde kullanabilirsiniz. 'do while' döngüsünde, 'while' koşulunda olduğu gibi...

    Özellikleri 'in' ile denetleme

    • Olmayan bir özelliği 'in' işlemiyle denetlemek istediğinizde WebTV çalışmaz.
    • Windows altındaki Netscape 4, Internet Explorer 5.0 ve Mac'ta Internet Explorer 'in' işlemini burada gösterildiği gibi kullanmaz.

    'for - in' döngüsündeki 'in' işleminin başka bir amacı vardır. Bir nesnenin adlandırılmış özelliklerini denetlemek için de kullanılır. Bir çok yerde koşul olmadan koşullular kullanmak en iyisidir. Bazen denetlenen özelliğin sonucu "doğru" bile olmayabilir. Belki değeri 0, boş dizi ya da null olabilir.

    Eğer özelliğin türünü biliyorsanız özdeşlik kullanarak denetleme olanağı doğabilir. Örnek:
    if( typeof( document.body.innerHTML ) == 'string' ) {
    
    Bir özelliği denemek için de 'in' işlemi kullanılabilir. Bu var oluşu denemenize de olanak verir (değişkenin o anda neyi var, ya da neyi o anda bulundurduğu anlaşılır). 'for - in' döngüsünde 'in' işlemi özelliğin adlarını döndürür. Burada da adın bir yazı dizisi olması beklenir. Kullanımı biraz sınırlar, çünkü yalnız adları tarayabilir ve bir özelliğin özel bir tür ya da değer taşıyıp taşımadığını belirleyemez.
    if( 'innerHTML' in document.body ) {
    
    Bu işlem IE'de koşulsuz koşullulardan 20 kez daha yavaştır. Pek çok tarayıcıda her iki seçenek de hemen hemen aynı sonucu verir. Burada en sık kullananı seçmek yararlıdır. Ama çok özel bir amaç varsa 'in' işlemini kullanabilirsiniz.

    Koşul içinda atamai yapma

    Javascript bir koşulu denerken bir değikene atama yapılmasını da sağlar. Bir koşul içinde yer alabildiğinden 'if', 'for', 'while' ve 'do - while' deyimleriyle kullanılabilir.
    if( x = document.getElementById('mydiv') ) {...}
    
    do {
      alert( node.tagName );
    } while( node = node.parentNode );
    
    IE bu işlemi bir diziyle yaparsanız, dizinin sonunu geçerse hata mesajı verir

    Continue ve break deyimleriyle Etiketler (label)

    Labels

    Etiketler 'while', 'do - while', 'for', 'for - in' ve 'switch' denetim deyimlerininde kullanılır. Yazım kuralı:
    Etiket_adı:
    Denetim Yapısı
    
    Etiketler Javascript için hemen hiç kullanılmaz.

    break deyimi

    switch, for, for-in, while ya da do - while idenetim yapılarında break kullanmak programın deyim sonuna zıplamasını sağlar. Örnek:
    for( var x = 1; x < 5; x++ ) {
      var y = 1;
      while( y < 7 ) {
        y++;
        if( y == 5 ) { break; }
        document.write(y);
      }
    }
    
    y değeri 6 ise kodlama while döngüsünün sonuna sıçrar. Ama bunu kullanınca:
    myForLoop:
    for( var x = 1; x < 5; x++ ) {
      var y = 1;
      while( y < 7 ) {
        y++;
        if( y == 5 ) { break myForLoop; }
        document.write(y);
      }
    }
    
    y değeri 5 ise kodlama for döngüsünün sonuna sıçrar.

    continue deyimi

    'for', 'for - in', 'while' ya da 'do - while' denetim yapılarında, continue kullanmak programın deneme koşuluna sıçramasını ve 'her_zaman_bunu_yap' bölümündekileri yapmasını sağlar. Örnek:
    for( var x = 1; x < 5; x++ ) {
      var y = 1;
      while( y < 7 ) {
        y++;
        if( y == 5 ) { continue; }
        document.write(y);
      }
    }
    
    Bu kodlama y değeri 5 olunca deneme koşuluna sıçrar, 5 hiç yazılmaz ama 6 ve 7 yazılır. Yerine bu kullanılırsa:
    myForLoop:
    for( var x = 1; x < 5; x++ ) {
      var y = 1;
      while( y < 7 ) {
        y++;
        if( y == 5 ) { continue myForLoop; }
        document.write(y);
      }
    }
    
    Burada kodlama x değerini döngünün bir parçası olarak arttırır ve koşulu yeniden dener.