Professional Documents
Culture Documents
Ileri Seviye Javascript
Ileri Seviye Javascript
ndeks
Giri Fonksiyonlar 1. Parantez Bloklar 1. Argmanlar 1. Fonksiyonlar in Method ve Alt Deiken Tanmlamak 1. Apply 1. Call 1. Prototype 1. Caller 1. Blm Sonu Pratikleri Diziler Nesneler leri Seviye OOP
Giri
Bu dkmanda Javascript'in deneysellie dayanan doasna uygun biimde, web tabanl program retmenizi salayacak bilgileri vermeye altm. zellikle stnde durmanz gereken konu olan fonksiyonlarda, kitaplarda yeralmayan ileri teknik ve pratikleri anlattm. Dkmandan iyi verim almak iin, Rainbow9'dan faydalanabilirsiniz. Rainbow9, geen yl hazrladm, javascript deneyleri yapmay ve web tabanl programlar gelitirmeyi salayan bir programdr.sterseniz Firefox'un Firebug eklentisinden de faydalanabilirsiniz.Rainbow9, Firebug'n aksine baz mobil tarayclar dahil tm tarayclarda kurulmaya gerek olmadan alr. Rainbow9: http://www.rainbow9.org Firebug: http://www.getfirebug.com Dkman okuyup bitirdikten sonra daha deneysel ve iyi tekniklerle kod yazacanz, kod standartnz gelitireceinizi umut ediyorum. Sabr ve gayretlerinizin karln almanz dileiyle, Azer Koulu <http://azer.kodfabrik.com> Destekleyen, yardm eden, moral verenlere teekkr ederim: Annem Nuray Koulu, Can atalyrek, Hakan Bilgin, Muhammed Daud
Fonksiyonlar
C tabanl dillerde her i veya alt i fonksiyonlar tarafndan yrtlr.Fonksiyonlarn genel kullanm ekli, argman tnelinden veri gnderip, bilgi k beklemektir.Genel yazl inceleyelim:
(argman1,argman2,argman3...)
ECMAScript'in kullandmz srmnde, argmanlar iin PHP veya Python dillerinde olduu gibi varsaylan deer atanamaz.Deer atanmayan argmanlarn tantclar yine tanmlanr ancak "undefined" trnde olurlar.Argmanlar sadece tanmlandklar fonksiyonda altrlabilirler.Global blokta tanmlanan deikenlere fonksiyonlardan eriilebilir. Bir fonksiyonda en son, fonksiyondan geriye deer dndrlmesini salayan "return" ifadesi altrlr.Eer bu ifadeden sonra fonksiyonun ierii bitmediyse, ECMAScript bu ierii grmezden gelir. Fonksiyonlar eitli biimlerde tanmlanabilir, ilk olarak tantc ve eit iareti kullanarak klasik biimde tanmlayalm:
function islem(){}
rnek olarak argman tnelinden ald iki saynn toplam geriye dndren bir fonksiyon tanmlayalm:
ECMAScript'in Function() nesnesi sayesinde, kod blou tantc string tipinde belirtilerek, programn akna gre ekillenen fonksiyonlar tanmlanabilmektedir:
>>> var durum = 'Negatif'; >>> var durumuAyarla = function(){ durum = 'pozitif' }
Bu rnekteyse programn global blounda "durum" adnda bir deiken ve "durumuAyarla" adnda, "durum" deikeninin deerini string tipinde "pozitif" deeriyle deitiren bir fonksiyon oluturuluyor.altrp deneyelim;
Parantez Bloklar
Fonksiyon tipindeki verilerin almasn incelediimiz rneklerde parantezlerin saladn gryoruz.Parantezler ilevsel olarak pek ok konuda fayda salasa da, pek ok zaman yazlan kodun daha anlalr olmas iin blok oluturmada kullanlr.nce ne gibi ilevlerde kullandmza gzatalm.Birinci rnek matematiksel ilemlerde gruplama yaparken kullanlan parantezler zerine:
>>> 1.toString() missing ; before statement [Break on this error] 1.toString() javascript: with ... (line 1) >>> 1.0.toString() "1" >>> (1).toString() "1"
Gelelim nc rnee.Ecmascript'te her fonksiyon blou parantezler iine alnabilir.Ve elbette, parantez iine alnm kod blouna altrma komutu gnderilebilir.Bu yntem daha sade ve temiz grnen kodlar yazmay salar, nk fonksiyonu yazdktan sonra tantcy armaya gerek duyulmaz. Klasik yntemle yazlan bir fonksiyonun arma ilemiyle, parantez blounun kodlarn karlatralm:
>>> var merhaba = function(){ return "Merhaba" } >>> merhaba(); Merhaba >>> (var merhaba = function(){ alert("Merhaba"); })(); "Merhaba"
lk rnekte fonksiyonu tanmladk ve ardndan tantcsn kullanarak altrdk, ikinci rnekteyse fonksiyonu parantez bloklarnn iine alp altrdmz iin, tantcyla arma yaptmz satra gerek kalmad.Tahmin edeceiniz zere, aslnda parantez bloklarn kullanrken tantc kullanlmayabilir:
Argmanlar
Fonksiyonlar, sadece faaliyet alanlarnda eriilebilir durumda olan deerler alabilirler.Bu deerlerin tantcs, fonksiyon oluturulurken argman tnelinde yazlr.Fakat gnderilen argmanlar iin tantc belirtmek zorunlu deildir, tantc olsun veya olmasn, fonksiyon iindeki "arguments" tantcl deiken argman tnelindeki tm verileri saklar. Diziler, tek tantcnn altnda veri paralarn tantcya ihtiya kullanmadan saklamay salayan veri trdr, rnek olarak herbiri tek bana bir deer olan birka elmay tutan sepeti dnelim.Sepeti tutan el, programmz altran browser olmal :) Fonksiyonlardan bir sonraki konu balnda dizileri daha detayl inceleyeceiz. Az nce szn ettiim "arguments" deeri, fonksiyonlarn argman tnelinden gelen tm deerleri sral olarak saklayan bir dizidir.Tantcs olsun veya olmasn, browserlar gnderilen tm argmanlara erimemizi salar.Bir rnek;
>>> var argumanlar = function(){ return arguments; } >>> argumanlar(3,5); 3,5 >>>
rnekte "argumanlar" adnda, tek ilevi kendisine gelen argmanlar geri dndrmek olan bir fonksiyon oluturduk ve bu fonksiyona gnderdiimiz argmanlarn bize dizi tipinde geri dndn grdk.Toplama rneini "arguments" dizisinin elemanlarn seip ilem yaptrarak yeniden ele alalm:
>>> var islemci = function(){ this.aciklama = "merhaba dnya!" this.toplama = function() { return arguments[0]+arguments[1]; } this.cikarma = function(sonuc) { return arguments[0]-arguments[1]; } } >>> var islem1 = new islemci(); >>> islem1.toplama(3,5); 8 >>> islem2.cikarma(3,5); -2
islemci adnda, toplama cikarma methodlarn ieren bir fonksiyon yarattk ve ardndaki satrda, islem1 tantcsna yeni bir islemci objesini atadk.Bu kez, az nce yazdmz islemci objesinde, prototype kullanarak yeni bir alt method yaratalm;
>>> islemci.prototype.carpma = function(){ return arguments[0]*arguments[1]; } >>> var islem2 = new islemci(); >>> islem2.carpma(3,5); 15
prototype
Klonlanabilir nesnelerin ortak etki alanna sahip olmasn salayan bir deerdir.Eer prototype kullanmadan tanmlama yaparsak, alt methodu olduumuz objenin etki alanna yani ierdii deerlere eriemeyiz.Buna bir rnek verelim:
>>> islemci.prototype.aciklamayiGoster1 = function(){ return this.aciklama; } >>> islemci.aciklamayiGoster2 = function(){ return this.aciklama; }
Grevleri islemci objesine ait aciklama deerini dndrmek olan etki alanlar farkl, iki tane fonksiyon tanmladk.lk tanmladmz fonksiyonu deneyelim:
>>> function test(){ var _deger = "merhaba dnya!"; this.degeriGetir = function(){ return _deger; } }
Yukaridaki rnekte test adnda bir fonksiyon oluturduk ve biri dardan eriime kapal, iki deer oluturduk.
>>> test1 = new test(); >>> test1._deger undefined >>> test1.degeriGetir() "merhaba dnya!"
Apply
apply Javascript'in isvire aksdr.Bu zellik sayesinde, fonksiyonlar birbirlerinin yaplarnn stne ina edilebilir ve bunun saymakla bitmez faydalarndan biri, modern object oriented dillerinin kaltm zelliini bize salamasdr.rnein, kimlik bilgileri ieren "kii" objesi zerine, skor ve benzeri bilgileri ieren "oyuncu" objesi oluturalm:
>>> var kisi = function(adsoyad,yas,dogumyeri){ this.adsoyad = adsoyad; this.yas = yas; this.dogumyeri = dogumyeri; } >>> var arda = new kisi("Arda Koulu",17,"Kars"); >>> arda.dogumyeri "Kars"
Kii objesini inceleyelim; bir fonksiyon oluturduk ve argman tnelinden gelen veriyi bu fonksiyona alt deer olarak atadk.Ardndaki satrda "arda" deerini "new" operatryle yeni bir kii olarak tanmladk.Kii objesini oluturduumuza gre, oyuncu objesine de geebiliriz:
>>> var oyuncu = function(adsoyad,yas,dogumyeri,takim,skor){ this.takim = takim; this.skor = skor; kisi.apply(this,arguments); } >>> var kemal = new oyuncu("kemal akn",15,"antalya","maviler",3); >>> var ege = new oyuncu("ege akn",10,"izmir","krmzlar",2); >>> kemal.takim maviler >>> ege.dogumyeri izmir
Oyuncu adnda bir nesne oluturduk, argman tnelinden beklediimiz deerleri tantclarna tanmladktan sonra, takim ve skor alt deerlerini atadk.Ardndan gelen satrda ise, kisi objesinin apply methodunu altrdk ve "this","arguments" argmanlarn gnderdik. "this" argman, kii objesinin hangi fonksiyon tarafndan arldn gndermek iin kullanlr.arguments Argmanysa, apply methoduyla arlan fonksiyonun argman tnelinden bekledii argmanlar gndermemizi salar."arguments" deeri, oyuncu fonksiyonuna gelen deerleri ierdiinden, "oyuncu"
Call
call fonksiyonu tpk apply gibi, fonksiyonlar kendi belirlediimiz etki alan ve argmanlarla altrmamz salar.Bir problemin zmn anlatarak rnek yapalm, javascript arguments dizisinin alt methodlarn kullanmamza olanak tanmaz.Deneyelim;
Call ile kaltm Kaltm ilikileri kurmak iin apply'den daha ok tercih edilen methoddur.Mantk olarak pek farkllk yok, istenen objeye "scope" ve argmanlar gnderiliyor:
>>> var kisi = function(adsoyad,yas,dogumyeri){ this.adsoyad = adsoyad; this.yas = yas; this.dogumyeri = dogumyeri; } >>> var oyuncu = function(adsoyad,yas,dogumyeri,takim,skor){ this.takim = takim; this.skor = skor; kisi.call(this,adsoyad,yas,dogumyeri); } >>> var kemal = new oyuncu("kemal akn",15,"antalya","maviler",3); >>> var ege = new oyuncu("ege akn",10,"izmir","krmzlar",2); >>> kemal.takim maviler >>> ege.dogumyeri izmir
rnekte grdnz gibi, apply ile temel farkllk call methodunun argmanlar serbest biimde gndermemizi salamas.
Prototype
Prototype' bir binann iskeletine benzetebiliriz, hatta bu benzetmeye tahmin ediyorum birka yz dkmanda daha rastlayabilirsiniz nk prototype benzetmeden daha te, fonksiyonlarn iskeletidir. Prototype deerlerinin tipi objedir.Yani bir objeyi alp, bir fonksiyonun iskeleti olarak kullanmak mmkndr.Tabii bunun tam tersi durum da szkonusu. Fonksiyonlarn klonlanarak objeye dntrlmesini anlatrken bir detay atlamtk; objenin zellikleri fonksiyonun tanmland blokta olmak zorunda deil.Oluturduumuz fonksiyonun iskeletine ulaabilir ve eitli eklemeler yapabiliriz.imdi adm adm bir fonksiyon yazalm ve konsolun dndrd deerleri yorumlayalm:
>>> var kisi = function(adsoyad,yas,dogumyeri){ this.adsoyad = adsoyad; this.yas = yas; this.dogumyeri = dogumyeri; } >>> kisi.prototype Object: There are no properties to show for this object.
rnekte kisi adnda bir fonksiyon oluturup iine adsoyad,yas,dogumyeri zelliklerini yazdk.Ardndaki satrda prototype' incelediimizde, bo bir objenin dndn gryoruz.Bu durumdan unu karmalyz, iskeletin inas prototype objesi dnda yaplamaz.Veya yle zetleyelim, fonksiyonun iinde iskelet oluturamayz.
>>> kisi.prototype
Object: (meslek = null) >>> selcuk = new kisi("seluk koulu",48,"mardin"); >>> selcuk.meslek null
Bu rnekteyse selcuk adnda bir obje oluturduk ve meslek zelliini sorguladk.Dnen sonucun null -bu bizim belirlediimiz bir varsaylan deerdi- olduunu gryoruz. Buradaki problem, iskelete sonradan eklenen meslek zelliini constructor'a nasl dahil edeceimiz.Bu i iin constructor'n yeniden yazlmas kanlmazdr;
>>> var kisi = function(adsoyad,yas,dogumyeri,meslek){ this.adsoyad = adsoyad; this.yas = yas; this.dogumyeri = dogumyeri; this.meslek = meslek; } >>> fikretkizilok = new kisi("fikret kzlok","60","stanbul","Mzisyen"); >>> fikretkizilok.meslek "mzisyen"
Bu rnekte dikkat etmemiz gereken, kisi fonksiyonunun eski iskeleti devralmas.Peki bu durumda henz tanmlanmam fonksiyonlarn iskeleti oluturulabilir mi? Evet, oluturulabilir. Bunu denemek iin yeni bir fonksiyon yazalm:
kargo.prototype.alan = null; kargo.prototype.gonderen = null; kargo.prototype.kargoicerigi = null; function kargo(alan,gonderen,kargoicerigi){ this.alan = alan; this.gonderen = gonderen; this.kargoicerigi = kargoicerigi;
} >>> kargo.prototype.ucret 0
Grld gibi, undefined deeri olan bir tantc altnda iskelet oluturduk ve ardndan bu tantcya fonksiyon deeri verdik.Son satrda ise, tantc deer almadan oluturduumuz iskeletin alr durumda olduunu onayladk.Biraz nce yazdmz kisi nesnesinden de faydalanarak kargo'nun kullanmna bir rnek verelim:
>>> var azerkoculu = new kisi("azer koulu",20,"ka","web gelitirici"); >>> var billgates = new kisi("bill gates",53,"seattle","iadam"); >>> var yeniKargo = new kargo(azerkoculu,billgates,"mozilla stickers");
Prototype ve Browser Nesneleri Javascript'in disable olmad durumlar saymazsak, browserlar her HTML belgesinde javascript komutlarnn almasn salayan bir zemin oluturur.String,Number,Function,Array,Object nesneleri browser szettiimiz ekirdekte yer alan nesnelerden birkadr. Yazdmz her say Number objesinden, her yaz String objesinden trer.Ve tahmin edeceiniz gibi, bu deerlerin methodlar, ekirdekteki nesnelere baldr.String nesnesinin methodlarndan birini deneyelim:
12
Aklnza u soru gelmi olmal: Peki ondalk hanelerin nokta iaretleriyle methodlarnki karmaz m? Evet karr.Bunun iin saylar parantez iine alnr, veya ondalk hanesinden sonra method yazlr. rnekte grdnz gibi, Number snfndan treyen say deerlerinin altnda topla methodu kendiliinden gelmektedir. Kk bir ipucu: prototype Obje tipindedir yani Object snfndan tremitir.imdi browser'mz heyecanlandracak birka deneme yapalm:
Caller
Fonksiyonlarn nasl arldn anlamak iin, alt zellikleri olan "caller" kontrol edilir, eer herhangi bir fonksiyon iinde arlmadysa, "null" deerini dndrr.Bu zellik "fonksiyonAd.caller" biiminde kullanlr:
>>> var merhaba = function(){ return merhaba.caller; } >>> merhaba() null >>> (function(){ return merhaba() })() (function(){ return merhaba() })()
rnekte, "merhaba" adnda, kendisini aran fonksiyonu dndren bir fonksiyon oluturduk.Global blokta ardmz satrda "null" deer dnerken, dierinde fonksiyonun kendisi dnd. rnek olarak, yazdmz fonksiyonun baka bir fonksiyon iinden arlmasn engelleyebiliriz;
>>> var merhaba = function(){ if(merhaba.caller!=null) return "Bu fonksiyona baka bir fonksiyonun iinden eriemezsiniz." return "Merhaba!"
Dizi konusu gibi, ileride detaylca inceleyeceimiz konulardan biri de koullar.Yukardaki rnein ilk iki satrnda, "merhaba.caller" deerini kontrol ettik ve eer "null" deilse, yani bir baka fonksiyonun iinden ar yapldysa, "Merhaba" yerine uyar metni dndrdk."return" komutu verildikten sonra yorumcunun fonksiyondan ktn hatrlayalm. Internet Explorer ve eval() stisnas "Caller" Internet Explorer, Mozilla gibi popler tarayclarn destekledii, aslnda standart d bir zelliktir.Fakat Internet Explorer "eval()" komut blounda altrlan fonksiyonlar iin de caller deerini "null" dndrmektedir.Kontroller yaplrken bu durumu dikkate almak gerekir.
var deneme = function(){ alert(this.adres); } deneme(); // undefined deneme.call({ "adres":"google.com" }); // google.com
Deneme adnda bir fonksiyon oluturduk ve ikinci satrda altrdk.Fonksiyonumuz altnda, kendisine ait "adres" adnda bir methodu arad ve
byle bir method tanmlanmadndan undefined deer dnd.nc satrda ise deneme fonksiyonunun call methoduna bir obje gnderdik.Deneme fonksiyonu bu kez altnda kendisinin etki alann gnderdiimiz Bu problemin nasl alacan call ve apply balklarnda detaylaryla anlattm, imdiyse bu ii olduka pratik bir hale getirelim. rnein, herhangi bir fonksiyonu u biimde aralm ve istediimiz scope'u uygulayalm:
adnda bir boolean ieren deneme objesi oluturduk, imdi bu objeye iki ayr yolla erielim:
>>>var deneme = { kontrol: true }; >>>var kontrolDegeri = function(){ return this.kontrol; }; kontrolDegeri(); // undefined dner kontrolDegeri.call(deneme); // "true" dner
Kontrol deerini ilk armzda bize deer dnmedi ancak ikinci arma biiminde istediimiz deer dnd.Burada call methoduna scope deeri olarak deneme objesini gnderdik ve bylece fonksiyonun iindeki this deeri, deneme objesine referansland.lk satrda ise fonksiyonun ierii scope olarak window objesine eritiinden, istediimiz deer dnmedi. Cevap 3) Bir veri trne method atamak iin, o veri trnn constructor' zerinde ilem yapmak gerekir.Daha ayrntl bilgi almak iin, prototype balna dnn. Soruda bizden isteneni daha ak hale getirelim; her fonksiyonun "curry" adnda bir methodu olacak ve biz bu methoda istediimiz scope'u gnderdiimizde, bize yeni bir fonksiyon deeri gnderecek.Elde ettiimiz yeni fonksiyonu dilediimiz gibi altrabileceiz, yani fonksiyonumuz apply veya call ilemlerindeki gibi, scope gnderilince hemen almayacak.nce rnek kullanm inceleyin:
Methodunun yazmnda ncelikle dikkat etmemiz gereken, bir fonksiyon deeri dndrecek olmamz, bir dier nemli unsursa, argmanlar da kullanacak olmamz.call ve apply balklarnda, argmanlarn nasl kullanldn anlatmtm, tekrar gzatabilirsiniz.Yazmaya balayalm:
>>> Function.prototype.curry = function(scope){ var fn = this; var scope = scope||window; return function(){ fn.apply(scope,arguments); } }
Grdnz gibi pek karmak bir zm olmad.lk satrda, fn adnda bir deer tanmladk bunun sebebi, geri dndrdmz fonksiyon deerinin iinden, st fonksiyona eriemeyiimiz.Ancak st fonksiyon blounda tanmladmz deerler, birbirine eriebilir.Bu yzden, scope deerini de tekrar tanmladk.Genellikle mantksal sorgulamalarda kullandmz "veya" ifadesinin grevi ise, argman olarak gelen scope deeri null,false veya undefined olduunda, window deerini dndrmektir.Daha sonraki satrda ise, bir fonksiyon deeri dndryoruz.Yeni fonksiyonun ieriine baktmzda bu kez call deil apply kullandmz grrsnz.Bunun sebebi, call methodunun argmanlar array tipinde deil, tek tek almas.apply ise bunun tam tersine, ilk argmandan sonra bir argmanlar ieren dizi deeri bekler.Gnderdiimiz arguments deeri, yeni fonksiyona gelen argmanlar ieren dizi deeridir.Bunun hakknda daha fazla bilgi istiyorsanz, argmanlar balna dnn.
Diziler: array
stenen veri paralarn tr ayrm yapmadan bir araya getirip gruplayan veri trdr.ECMAScript dizi elemanlarnn tantclarn sra numaras olarak tanmlar.Deer atama ilemi keli parantezler iinde dizi elemanlarn virglle ayrarak yaplr:
Program iinde diziye erimek istendiinde, dizi elemanlarnn anahtarlarn kullanmamz gerekir.Burada anahtar, dizi elemannn sra numarasdr ve sra numaralar sfrdan balar, yani son dizi elemannn sra numaras dizi uzunluundan bir eksiktir.rnek olarak, az evvel oluturduumuz tekSayi dizisinin ikinci elemanna erielim:
Fakat grld gibi bu pratik bir tanmlama biimi deildir. Az evvel herhangi bir trde veri tutulabildiine deinmitik, bu konuda bir rnek hazrlamak iin, fonksiyon bilgimizi de kullanarak toplama ve karma yapan bir dizi oluturalm:
>>> var deneme = ["merhaba","dnya"] >>> deneme.pop(); "dnya" >>> deneme ["merhaba"]
push Argman tnelinden gelen deerleri dizinin sonuna ekleyen method.Geriye dizinin yeni uzunluunu dndrr.
Push fonksiyonunu concat yerine kullanmak iin, fonksiyonlarn apply methodundan ve prototype objesinden faydalanlr.Bu iki konuda detayl bilgiyi fonksiyonlar balnda bulabilirsiniz.Gelelim rnee;
>>> var dizi1 = [1,2]; >>> var dizi2 = [3,4]; >>> var dizi3 = [5,6]; >>> var dizi4 = [7,8]; >>> dizi1.concat(dizi2); [1,2,3,4] >>> Array.prototype.push.apply(dizi3,dizi4); 4 >>> dizi3 [5,6,7,8]
rnekte concat methodunun kullanmn hatrladk ve ardndan apply methodunu ararak dizi3 ile dizi4 birletirdik. slice Dizi deerlerinin iinden istenen index aralklarn armay salar;
rnekte, b deerine ilk oluturduumuz a deerini atadmzda, iki deer birbirine referansland.Bunu anlamak iin b dizisine yeni bir say ekledik, a dizisini kontrol ettiimizde ayn saynn a'ya da eklendiini grdk.Aslnda b'ye eklendiimiz a'ya eklenmedi, daha dorusu biz hem a'ya hem b'ye ekleme yaptk. Bu zelliin at problemlerle ilgili bir rnek yapmak iin dizi tipinde alt deeri olan bir snf tanmlayalm:
var deneme = function(){} deneme.prototype.dizi = []; var nesne1 = new deneme(); var nesne2 = new deneme(); nesne1.dizi.push(1); nesne1.dizi nesne2.dizi
rnekte grdnz gibi, deneme iskeletinden treyen tm objelerin dizi tipindeki alt deeri birbirine referansl.Biri deiince dieri de deimekte.imdi sorulara geelim: SORULAR Soru 1) Dizilerin klonlanmasn salayan, dizi.clone() eklinde altrlabilen bir method yazn.Dizilerin iie olabileini dikkate aln. Soru 2) Birinci sorunun cevabn, fonksiyonlarn iskeletinde yaanan referans probleminin zm iin uygulayn. CEVAPLAR Cevap 1) Bu problemin zm iin bu dkmanda bahsetmediim dngleri ve kontrol ifadelerini biliyor olmalsnz.Snflarn iskeletine method ekleme ilemi hakknda bilgi almak iin Fonksiyonlar konusundaki prototype balna dnn. Problemin cevabna geelim:
Array.prototype.clone = function(){ var gecici = []; for(var i=0; i<this.length; i++){ gecici.push( this[i] instanceof Array? this[i].clone():this[i] ); } return gecici;
}
rnekte, gecici adnda yeni bir dizi oluturduk ve dizi elemanlarn tek tek bu yeni diziye ekledik.Ve yeni diziyi geri dndrdk.Bu rnekteki en nemli satr, push fonksiyonuna veri gnderirken yaptmz kontrol:
Nesneler: object
Objeler, tpk diziler gibi, istenen veri paralarn gruplayan veri trdr fakat dizi elemanlarnn aksine, nesnelerdeki elemanlar iin tantc belirlenir. Dizilerdeki keli parantezlerin yerini ssl parantezler alr.Nesne elemanlar birbirlerinden yine virglle ayrlrlar.Fakat bu kez her veri paras iin bir tantc belirlenir, bu ilem iin "var" ifadesi ve eit iareti kullanlmaz, tantc yazlp hemen ardnda ":" kullanlr. rnein,
>>> var meslekler = { "azer koulu":"renci", "nuray koulu":"retmen" }; >>> meslekler.azer koulu // hatal tantc yazdk. SyntaxError: missing ; before statement >>> meslekler["azer koulu"] renci
Nesne tanmlandktan sonra yeni bir eleman ekleme-karma ilemi yapmak iin dizilerdeki push ve pop fonksiyonlar yerine, yine dizilerden alk olduumuz tanmlama biimi kullanlr:
>>> var meslekler = { "azer koulu":"renci", "nuray koulu":"retmen" }; >>> meslekler["arda koulu"] = "renci"
Bu veri tipinin esnek yaps sayesinde, ECMAscript'in OOP eksiklii tamamlanr.Dizilerdeki basit ilem dizisini, nesneleri kullanarak tekrar yazalm:
>>> var islem = { topla: function(sayi0,sayi1){ return sayi0+sayi1; }, cikar: function(sayi0,sayi1){ return sayi0-sayi1; } } >>> islem.topla(2,3); 5 >>> islem.cikar(2,3); -1 >>> islem.cikar(islem.topla(2,3),1); 4
Yaptmz rnekte, "islem" adnda bir nesnenin iinde, fonksiyon tipinde "topla" ve "cikar" adlarn tayan iki method oluturduk, ve birka deerle test ettik. rnekteki kodlama trnn, ilem yaptrdmz deerleri gruplama dnda zel bir ilevi yok.Peki dier programlama dillerinde alk olduumuz "new" operatryle oluturulan (klonlanan da denilebilir) snflar oluturulamaz m? Elbette oluturulur, rnekten ilerleyelim:
return sayi0+sayi1; }, cikar: function(sayi1){ return sayi0-sayi1; } } } >>> var islem1 = new islemci(5); >>> islem1.topla(3); // 5+3 = 8 8 >>> islem1.cikar(3); // 5-3 = 8 2
Uyguladmz son iki rnekteki farka dikkat edelim, ilk rnekte ilem yapan fonksiyon tipindeki verileri saklayan bir obje vard, ikinci rnekteyse, birinci rnekte saklanan objeyi "return" operatryle geriye dndren bir fonksiyon var. rnekteki "islem1", 'islemci`'nin argman tnelinden ald "5" deeri iin dndrd "topla" ve "cikar" fonksiyonundan oluan nesne deerini ald.Ardndaki satrlarda bu fonksiyonlar test ettik.
Object.Clone = function(){ var gecici = []; for(var i=0; i<this.length; i++){ gecici.push( this[i] instanceof Array? this[i].clone():( typeof this[i]=="object"? Object.Clone(this[i]): this[i] ) ); } return gecici; }
Diziler balnda kullandmz klonlama fonksiyona bir kontrol daha ekledik:
typeof this[i]=="object"?Object.Clone(this[i]):this[i]
Burada aslnda deeri instanceof ile Obje snfndan treyip tremediini de kontrol edebilirdik.Fakat browser bu kontrolde fonksiyonlar iin de pozitif deer dndrecektir. 2) Bu problemin zm aslnda olduka basittir, objeyi nce tanmlar sonra return operatryle geri dndrrz.Fakat bu zm dnmeyi pek gerektirmez, biraz daha dnp daha iyi yntem bulmalyz.Bu tip kolay problemleri nasl daha pratik ekilde zebileceimizi, tekniimizi ilerletmek iin nemsemeliyiz.zme geelim:
function deneme(){ return ({ "Init": function(){ alert("Init fonksiyonundan merhaba!"); return this; } }).Init() }
Parantez bloklarn kullanarak biraz daha iyi bir zm kullandk.Buradaki zmn z Init fonksiyonunun iinde bulunduu objeyi dndrmesi. Fonksiyonlar, dizileri ve objeleri pekitirdiimize gre, leri OOP Teknikleri konusuna geebiliriz.
function deneme(){ this.zellik1 = deer; } var yeni = new deneme(); function deneme(){ } deneme.prototype.zellik1 = deer; var yeni = new deneme(); function deneme(){ } deneme.prototype = { "zellik1":deer; } var yeni = new deneme();
Objeler balndan karacamz yaplarsa unlar:
var deneme = { "zellik1":deer; } var yeni = Object.Clone(deneme); function deneme(){ return { "zellik1":deer } }
Her iki tekniin de profesyonel web projelerinin pek ounda kullanld grlr, ancak kod standartna gre yazm stilleri biraz daha deiim gsterecektir.rnek olarak u an altm irketin kod standartna gre bir snf oluturalm. Obje: Banka Hesab Deerler: ad soyad, bakiye, bor limiti lemler: Para Gnder, Para Yatr
function account(){ } account.prototype = { "_balance":0, "_limit":0, "_name":"", "getBalance":function(){ return this._balance; }, "setBalance":function(value){ this._balance = value; }, "getLimit":function(){ return this._limit; }, "setLimit":function(value){ this._limit = value; }, "getName":function(){ return this._name; }, "setName":function(value){ this._name = value; }, "SendMoney": function(value){ this.setBalance(this.getBalance()-value); }, "Invest":function(value){ this.setBalance(this.getBalance()+value); } }
Bu yazm biimini anlamaya alalm, neden deiken adlarnn nnde underscore iareti var? Neden her deiken iin get/set methodlar yazlyor? Underscore koymamzn nedeni browser'n reserveli kelimeleriyle akma olmamasn salamak.rnein "class" adnda bir deer oluturmamz gerekirse, webkit ve internet explorer yazdmz kodu durduracaktr.Bunun iin underscore ile iareti kullanrz. Peki, bir deeri isterken, veya ayarlarken, baka bir ilem yapmamz gerekiyorsa ne yaparz.Veya esas deeri, istenen ekle gre szerek vermemiz gerekiyorsa? Bu tip durumlarda standart bozulur, veya kodun ak deiir.Byle durumlar iin get/set zellikleri yazmak daha doru olacaktr.Peki, oluturduumuz bu objede get ve set fonksiyonlar iinde szme vb. ilemler yaplyor mu? Hayr.Bu unsuru aklmzda tutalm, birazdan tekrar dneceiz.
Son iki satrda ilem yapan fonksiyonlar, ba harfleri byk ekilde yazdk.nk ortam deerlerinden ayrlmalar gerekiyordu. Elimizde iki nemli unsur var: birincisi nemsiz yere get ve set kullanmamak.Yani gerektiinde yazmalyz.Fakat yazmasak ta standart bozulmamal, makine kendisi bizim yerimize rutin ilemleri yerine getirmeli.Dier husus, ilem yapan fonksiyonlar ortam deerlerinden ayrmak.Bu iki unsuru toparlarsak nasl bir obje yapsna ihtiyacmz olduuna karar verelim.Genel kullanm ekli yle olsun:
var azer = new account(); azer.environment.setName("Azer Koulu"); azer.environment.setBalance(1000); azer.environment.setLimit(2000); // ilem yapan fonksiyonlar kullanalm: azer.sendMoney(500);
rnekte grdnz gibi, ortam deikenlerini alt objeye yerletirerek ilem yapan fonksiyonlardan arndrp biraz daha dzenledik. Bu kullanm rneinden ilerlemek istediimizde karmza kacak ilk sorun, environment objelerinin referanslanarak birbirine bal hale gelmesidir.Sadece environment objesini dnmeyelim, normalde prototype zerinden snf oluturmaya altmzda, dizi ve obje tr deerlerin hepsi birbirine referanslanacak ve programmz bozacaktr. Bu problemleri amak iin istediimiz gibi snf oluturmamz salayan bir arabirim gereklidir.
var account = new Interface; account.body = { "Invest":function(){ }, "SendMoney":function(){ } } account.environment = { "_balance", "_limit", "_name" } account = account.build();
Bu rnee ek olarak, extend ve constructor adl iki methoda ihtiyacmz var.extend, oluturacamz snf baka bir snf kapsyorsa kullanacamz method olacak.consturctor ise, oluturacamz snfn constructor' olacak.Bu noktada obje referans problemini constructor'da zdmz hatrlamalsnz. Okuduunuz dkman bu snf yazabilmenizi salamaya alt.Bu pratii yaparken kod standartnz gelitireceinize inanyorum, umarm dkman faydal olmutur. Sorunun cevabn m merak ediyorsunuz :) Interface adn verdiim snf, hazrladm Pi adl javascript ktphanesi iin yapmtm.te kodlar:
var interface = function(){ this.constants = {}; this.environment = {}; this.events = {}; this.body = {}; } interface.prototype = { "constant":{}, "constructor":function(){}, "environment":{}, "event":{}, "body":{}, "extend":function(OBJECT){ var body = Object.Clone(OBJECT.prototype); Object.Concat(this.body,body); Object.Concat(this.constants,body.constants); Object.Concat(this.environment,body.environment); Object.Concat(this.event,body.event); }, "build":function(){ var link = this; var fn = function(){ this.constants = Object.Clone(this.constants); this.environment = Object.Clone(this.environment); this.environment._parent_ = this; this.event._parent_ = this; link.constructor.apply(this,arguments); };
for(var item in this.environment){ if(item.substring(0,1)!="_")continue; var name = item, title = name.substring(1,2).toUpperCase()+name.substring( if(Boolean(this.environment["get"+title])==false) this.environment["get"+title] = new Function("return this."+name); if(Boolean(this.environment["set"+title])==false) this.environment["set"+title] = new Function("VALUE","this."+name+ } this.body.constants = this.constants; this.body.environment = this.environment; this.body.event = this.event; fn.prototype = this.body; return fn; } };
Sizin iin faydal bir dkman olduunu umut ediyorum.Sabrnzn ve gayretinizin karln almanz dilerim. Azer Koulu