JavaScript Temelleri

Bölüm 2

Temel Bilgiler

Bölüm 2 Sayfa 12

2.10 - Özel İşlemciler

Javascript programlama dilinde azımsanmayacak sayıda özel işlemciler bulunmaktadır. Bunların herbirinin değişik işlevleri vardır. Bu işlemcilerden, typeof, delete ve void, Satırıçi Ardışık Çoklu İşlemler İşlemcisi (Virgül İşlemcisi), işlemcileri, daha önce incelenmişti. Geri kalanları da burada incelemeye çalışacağız.

2.10.1 - Nesne oluşturma İşlemcisi (new İşlemcisi)

new İşlemcisini önceden de uygulamalarda kullandık. Bu bir tekli işlemcidir. Kullanımı,

new YapılandırıcıFonksiyon([argümanlar])
		

şeklindedir. Yapılandırıcı fonksiyonlar, Object(), Number(), String(), Boolean(), Array(), Function() gibi öntanımlı altı yapılandırıcı yanında, kullanıcı tanımlı yapılandırıcılar da olabilir. Yapılandırıcı fonksiyonlar, genel yapıları ile bir fonksiyondur ve argümanlarının olması isteğe bağlıdır. Öntanımlı nesne yapılandırıcılarının sadece kullanımları açıklanmıştır. Kullanıcı tanımlı yapılandırıcı fonksiyonları kullanıcının kendisi tasarlar, yazılım ve kullanımlarını yapar. Bu konuları ileride detaylı olarak inceleyeceğiz. Örnek olarak,

a = new Object(); 
		

şeklinde yeni bir öntanımlı Object nesnesi örneği yaratan Object() öntanımlı yapılandırıcı fonksiyonun bir argümanı yoktur. Bu işlem, prensip olarak, boş bir öntanımlı Object nesnesi örneği veya başka bir ismi ile boş bir nesne literali yaratır ve referansını a değişkenine atar. Bu işlem prensip olarak,

a= {}; 
		

işlemi ile eş anlamlıdır.

2.10.2 - Nesne Özelliklerine Erişim İşlemcisi (Nokta İşlemcisi)

Nesnelerin değer ve fonksiyon özelliklerine (metotlarına) erişim için nokta işlemcisi kullanılır. Kullanımı,

window.document.writeln('Doğum Günü'); 
		

şeklindedir. Nokta işlemcisi iki işlenenli bir işlemcidir. Sol işleneni kesin bir nesne değişkeni, sol işleneneni ise, bu nesnenin bir özellik veya metodudur. Sol işlenende hiçbir şekilde tırnak içinde ifadeler bulunamaz. Sadece özellik veya metot isminin kullanılması gerekir. Nokta işlemcisi için paragraf 2.6.4.1 de ayrıntılı bilgi verilmiştir.

2.10.3 - [] İşlemcisi

JavaScript programlama dilinde, [] İşlemcisi, dizi başalatıcısı (dizi literali oluşturma), dizi elemanlarına ve nesne özelliklerine erişim gibi çeşitli ve önemli işlevlere sahiptir. Bu kısımda bu işlevlerini inceleyeceğiz. [] İşlemcisi için paragraf 2.6.4.2 de ayrıntılı bilgi verilmiştir.

2.10.3.1 - Dizi Literalleri

Dizi literalleri, bir standart JavaScript dizi sınıf nesne örneği yani bir dizidir. Boş bir dizi, ister bir dizi başlatıcısı ile,

var ekip = [];
		

şeklinde, istenirse öntanımlı dizi yapılandırıcısı ile

var ekip = new Array();
		

şelinde tanımlanır. Her iki yöntemde de sonuç aynıdır ve ekip adında, boş bir dizi açılmış olur.

Dizi literalleri, yoğun diziler (dense arrays) adı verilen dizilerin başlangıç elemanları ile birilikte de açılabilir. Örnek olarak,

iletişim = ['teleks', 'faks', 'telefon']; 
		

şeklinde bir tanıtım,

iletişim = new Array('teleks', 'faks', 'telefon');
		

ile aynı işleve sahiptir. Her iki bildirimin de sonunda, iletişim adlı yeni bir dizi açılır ve ilk elemanı olarak 'teleks', ikinci elemanı olarak 'faks', üçüncü elemanı olarak, 'telefon' değerleri atanmış olur. Sonuç aynı olduğuna göre, yeni bir dizinin dizi literali olarak ve veya dizi yapılandırıcısı ile başlatılması kullanıcının seçimine bağlı olmaktadır.

2.10.3.2 - İlişkisel Diziler

İlişkisel diziler olarak adlandırılan yapılanma, önce boş bir dizi açılarak,

aylar= []; 
		

sonra bu boş diziye eleman atayarak,

aylar['Kasım'] = 'Kasım';
		

veya

aylar = {Kasım : 'Kasım', Aralık : 'Aralık'};
		

veya

aylar = {'Kasım' : 'Kasım', 'Aralık' : 'Aralık'};
		

hatta,

aylar = {Kasım : 'Kasım', 'Aralık' : 'Aralık'};
		

şeklinde gerçekleştirilir. Sonuçta, dizi indisleri sözel olan bir tür dizi elde edilir ve buna İlişkisel Diziler (Associative Arrays) adı verilir. Diziler büyük çapta verilerin işlenebilmesini sağlaması gerken yapılanmalardır ve bu işlevlerini tamsayı olan sayısal indislerinin döngü mekanizmalarından yararlanan otomasyon yöntemleri ile işlenebilme yeteneklerini kullanarak gerçekleştirirler. Sözel indisler bu otomasyon programları arasında sadece for .. in döngülerinden yararlanabilir ve bunun sonucu olarak otomasyon özellikleri son derece kısıtlıdır. Bu nedenle, ilişkisel diziler, prensip olarak aşırı otomasyon gerektirecek kadar aşırı sayıda eleman içerecek şekilde oluşturulmaz. Bunlar prensip olarak aynı diziler gibi sadece tek veri olarak kullanılacak, az sayıda eleman içerecek, genellikle sözel indisleri dolayısı ile erişimleri açıklayıcı olması için tercih edilmiş yapılanmalar olarak uygulanırlar.

İlişkisel dizilerin teknik olarak dizi olmamalarına karşın, dizilerle karıştırılması, JavaScript programlama dilinde, dizilerin de bir nesne türü olmasından kaynaklanan dizi-nesne analojisinden dolayıdır. Bu analoji, dizi elemanı ile nesne özelliğinin aynı şey olduğunu belirtir. Örnek olarak,

aylar['Kasım'] === aylar['Kasım'] 
		

ifadesinde ilk terim ilişkisel dizinin ilk elamanını, ikinci terim ise nesne örneğinin ilk özelliğini belirtir. Yoksa tersi mi geçerli idi? Hangisinin hangi yapılanma olduğunun anlaşılması olanaksızdır. Bunun nedeni, her ikisinin de aynı yapılanma olduğunu yadsımamaktan geçer. Yani diziler prensip olarak nesnedir ve elemanları aynı zamanda nesne özelliiğidir. Ama tersi geçerli değildir. Diziler özel nesnelerdir ve her nesneye dizi özellikleri uygulanamaz. Sadece her ilişkisel dizi elemanına, nesne özelliğine erişir gibi, [] işlemcisi kullanılarak erişilebilir. Bundan sonra farklılıklar başlar. Örnek olarak dizi elemanları nesne özelliklerinin analogu olmalarına karşın, dizi elemanlarına nesne özelliklerine erişildiği gibi (eşdeğer olarak, ilişkisel dizilerin elemanlarına erişildiği gibi) nokta kovansiyonu ile erişilmez. Ayrıca nesne örneklerinin (ilişkisel diziler dahil) length özellikleri yoktur.

Diziler ve nesnelerin aynı olduğunu düşünmek kullanıcıya yarar getirmez. Dizilerin amaçları farklı, nesnelerin amaçları farklıdır. Diziler tüm özellik isimleri tamsayı olan nesnelerdir. Bir dizide milyonlarca eleman olabilir. Bir dizi başka bir diziden (kopyası olmadıkça) farklı fiziksel bir veridir. Nesne sınıfları, veri tipi oluşturulması amacı ile belirli bir yapılandırıcı fonksiyondan yararlanılarak yaratılan yapılanmalardır. Bir nesne sınıfının eğer bir nesne yapılandırıcısı tanımlanmışsa, gerçek fiziksel veri olan sonsuz sayıda sınıf örneği yaratılabilir. Diziler de böyle bir somut (öntanımlı) veri yapılandırıcısından yararlanılarak oluşturulmuş, yapıları aynı, özellik değerleri farklı, sınıf örneklerinden ibarettir.

Dizi literalleri ise, ne tam olarak bir dizi ne de tam olarak klasik bir nesne örneği sayılabilirler.

Dizi literalleri bir dizi sayılamazlar, çünkü length özellileri yoktur ve elemanları sayısal bir sıra indisine sahip değildir. Dizi literalleri eleman indisleri sözel olan özel bir dizi olarak düşünülebilir.

Dizi literalleri klasik bir nesne örneği sayılamazlar, çünkü tanımlanmış bir sınıf tanımlayıcları ( sınıf yapılandırıcıları) yoktur. Yapısına uydukları nesne sınfının tanımlayıcıları fiziksel olarak tanımlanmamıştır. Bunlar soyut sınıflardır ve Java programlama dilinin abstract sınıflarına benzerler, fakat bunlardan da daha soyutturlar çünkü hiçbir program adımında açıklanmamışlardır. Bir nesne literalinin soyut sınıfı ancak yapısı incelenerek anlaşılabilir. Yapılandırıcı fonksiyonları fiziksel olarak tanımlanmamış olduğundan dolayı, aynı yapıdaki örnekleri üretilemez, ancak yapıları başka bir değişkenin yapısı olarak kopya edilebilir. Zaten birden fazla değişkenin yapılarının aynı olması gereksinimi doğarsa, bu yapının soyut bir sınıf olarak uygulanması yerine, gerektiği gibi, doğudan doğruya bir yapılandırıcı fonksiyon olarak tanımlanması ve bu yapılandırıcı fonksiyonun (nesne sınıfının) örnekleri olarak tanımlanmaları, en doğrusu olacaktır.

İlişkisel diziler üzerine bir açıklama, about.com da Prof. Dr. Steven Chapman tarafından yapılmıştır. İlişkisel dizilerin kullanımları abartılmamamalı hatta çok gerekli olmadıkça kullanılmamaları, Andrew Dupont tarafından ayrıntılı olarak açıklanarak belirtilmiştir.

İlişkisel diziler, tarih verilerinin türkçeleştirilmesi için, b20.4.2 de uygulanmıştır.

2.10.3.3 - [] İşlemcisinden Nesne Özelliklerine Erişim İçin Yararlanılması

Daha önce, bölüm 2.6.4.2 de [] işlemcisi ile nesne özelliklerine erişimi görmüştük. Nesneler üzerinde daha fazala bilgimiz olduğundan bu konuya yeniden döneceğiz. Bir nesne örneğinin özelliğine [] işlemcisi yardımı ile ulaşılması için gerekli yazılım,

nesneÖrneğiAdı[ÖzellikAdı] 
		

şeklindedir. Özellik adı sayısal olabildiği sözel bir büyüklük de olabilir. Burada esneklik çok büyüktür ve bunun yararlı olduğu zararlı yönleri de görülebilir. Bir örnek üzerinde inceleyelim:

medya = [ 'Gazete', 'Televizyon'];
		

Burada medya bir dizidir ve elemanlarının indisleri 0 ve 1 dir. Bu bir dizi olduğundan elemanlarına nokta notasyonu ile erişilemez. Bu Elemanlara en doğru olarak şekilde, medya[0] şeklinde erişilir. Fakat, eğer medya['0'] şeklinde bir çağrı da olursa, JavaScript yorumlayıcısı sözel ifadeyi sayısala uyarlayarak (coercion) çağrıyı hatasız sonuçlandıracaktır. Bu olanak aslında hem iyi hem kötüdür. İyidir çünkü, sağladığı esneklik yararlı olabilir. Kötüdür çünkü hatalı bir gidiş doğru gibi sonuçlanırsa, bu tip mantık hatalarını bulmak çok güç olabilir.

Nesne örneklerinin özelliklerine erişim için en gerçerli yöntem nokta noktasyonudur. Örnek olarak yukarıda tanımlanmış olan aylar nesne literalinin ilk özelliğine, en geçerli olarak,

aylar.Kasım
		

olarak erişilir. Özellik adı sözel olarak tanımlandığı halde bu çağrı geçerli olmaktadır.

Aynı nesne örneğinin elemanlarına [] işlemcisi ile erişilmek istenirse, sadece aylar['Kasım'] şeklindeki çağrı geçerli olur. aylar[Kasım] şeklindeki çağrı tanrıya şükür ki hata verir.

Özellik isminin tek bir sözel değer olmayıp, tek bir sözel değere indirgenebilen bir sözel ifade olduğu zaman, nokta konvansiyonunun kullanılmasına olanak yoktur. Çünkü nokta konvansiyonunda noktadan sonra tek bir değer kullanılması gerekir. Noktadan sonra bir ifade kullanılamaz. Köşeli parantez konvansiyonun üstünlüğü ve kullanımının tek doğrulanabildiği kullanım alanı da budur. Özellik adının 'Ka' + 'sım' gibi bir sözel ifade olması halinde, özellik değerine erişim için tek seçenek köşeli parantez konvansiyonudur. Köşeli parantezler, sözel ifadeyi çözümleyerek tek bir sözel değer oluşturur ve bu değerle nesnenin özellik değerine erişim sağlarlar. Yoksa, sözel ifadeyi ayrıca çözümleyip, bir değişkene atayıp, o değişkenle nokta konvansiyonunu uygulayıp, nesne özelliğine erişimden başka çare kalmaz. Özellik adının sözel bir ifade olduğu aşağıdaki örnekte, nesne özelliğine erişim için, köşeli parantez konvansiyonu kullanılması zorunluğu vardır. Örnek olarak

			aylar['Ka' + 'sım']
		

şeklinde bir çağrı, [] işlemcisi ile kolayca çözümlenir ve çağrı gerçekleşir. Özellik adlarında bu sözel ifadelere, döngülerde kolaylık sağlanması için, bilgisayar tarafından oluşturulmuş sentetik özellik adlarında (alan adlarında) bazı durumlarda karşılaşılabilir.

2.10.4 - Fonksiyon Çağırma İşlemcisi ()

Fonksion çağırma işlemcisinin ilk işleneni daima bir fonksiyon tanımlayıcısı veya bir fonksiyon tanımlayıcısına indirgenebilen bir sözel ifadedir. İkinci işlenenin ise sayısı belli değildir. Bu işlenenler, ilk parantezden sonra virgül işlemcisi ile ayrılmış olarak parantezin içine yerleştirilirler. Geçerli bir fonksiyonda hiç argüman da olmayabilir. Son işlenen (argüman) da yazıldıktan sonra, parantez kapanır. Fonksiyon işlemcisi, argümanlarını değerlendirdikten sonra, ilk işleninin belirttiği fonksiyonu çağırır. Örnek:

a(x, y)
		

Javascript programlama dilinde fonksiyonlar birinci sınıf nesnelerdir ve değişkenlere atanabilirler. Bu atama fonksiyon çağırma işlemcisinin kullanılması ve kullanılmaması ile farklı olarak değerlendirilir. Eğer fonksiyon çağırma işlemcisi kullanılmazsa, atama

			d = a;
		

şeklinde olur. burada d değişkenine a fonksiyonun referansı (bellek işaretçisi) atanır. Bundan sonra d değişkeni a nın yeteneğini kazanır ve

d(14, 16);
		

şeklinde fonksiyonu çağırabilir. Fakat atamada fonksiyon çağırma işlemcisi de kullanılırsa durum değişir:

d = a(14, 16);
		

Bu durumda, öncelik sırası daha büyük olan sağ işlenen işlenir ve fonksiyon çağrılarak değeri hesaplanır. Sonra bu değer d değişenine atanır. Bu işlem sonunda d değişkenine fonksiyonun referansı değil, hesapladığı değer atanır ve d(4, 8) gibi çağrılar yapılamaz. Fonksiyonlar üzerinde daha fazla bilgi fonksiyon nesnesinin incelenmesi sırasında verilecektir.

2.10.5 - // İşlemcisi

JavaScript programlama dilinde, // İşlemcisi, düzenli deyim başlatıcısı (düzenli deyimi literali oluşturma), amacı ile kullanılmaktadır.

2.10.5.1 - Düzenli Deyim (RegExp) Literalleri

Düzenli deyimler, karakter dizigisi verileri ile uyuşma amacı ile hazırlanmış özel şablonlardan oluşur. Düzenli deyimler matematiksel bir tanımdır ve PERL scripting dili ile en geniş kullanım alanı bulmuştur. JavaScript, PERL kadar olmamakla beraber oldukça gelişmiş bir düzenli deyim desteği sağlamaktadır. Düzenli deyim sistematiği, ek-2 de açıklanmıştır.

Bir düzenli deyim literalinde //arasında düzenli deyim deseni, bunun dışında ise durum değiştiricileri veya anahtar olarak adlandırılan yönergeler bulunur. JavaScript sadece global arama anahtarı g, küçük/büyük harf farkının gözardı edilmesi anahtarı olan i ve çok satırlı düzenli deyim anahtarı olan m anahtarlarını destekler. Örnek bir düzenli deyim literali,

a = /^c*/gi
		

olabilir. Düzenli deyim öntanımlı nesne sınıfı bölüm 10 da incelenmiştir.

Valid XHTML 1.1