JavaScriptâte fonksiyonlar, âbüyülü dil yapısıâ deÄil yalnızca özel bir deÄer tipidir.
Daha önceden fonksiyon tanımlama için aÅaÄıdaki form kullanılmıÅtı.
function selamVer() {
alert("Merhaba");
}
DiÄer bir Åekilde de fonksiyon tanımlanabilir. Bu da fonksiyon ifadesi olarak adlandırılır.
AÅaÄıdaki gibi görünür:
let selamVer = function() {
alert("Merhaba");
};
Burada fonksiyon yaratıldı ve doÄrudan deÄiÅkene atandı, tıpkı diÄer dillerde olduÄu gibi. Fonksiyonun nasıl tanımlandıÄına bakmaksızın, bu fonksiyon sadece selamVer içinde saklanan bir deÄerdir.
Yukarıdaki kod örneklerinin anlamları aynıdır: âbir fonksiyon yarat ve bunu selamVer deÄiÅkenine ataâ
Hatta yazdıÄımız fonksiyonu alert ile ekrana basmak da mümkündür.
function selamVer() {
alert("Merhaba");
}
alert( selamVer ); // fonksiyonun kodunu gösterir.
Dikkat ederseniz son kodda () bulunmamaktadır. Bundan dolayı selamVer fonksiyonu çalıÅmayacaktır. Bazı dillerde ne zaman fonksiyonun ismini verseniz çalıÅır fakat JavaScriptâte çalıÅabilmesi için () kullanmanız gerekmektedir.
JavaScriptâte fonksiyonlar deÄer olduÄundan dolayı bunlarla uÄraÅılabilir. Yukarıdaki kod ekrana kaynak kodunu basar.
Tabiki selamVer() diye çaÄırılabildiÄinden dolayı özel bir deÄerdir.
Fakat yine de deÄerdir. Bundan dolayı diÄer deÄerlerle uÄraÅıldıÄı gibi bununla da aynı Åekilde çalıÅılabilir.
ÃrneÄin bir fonksiyon baÅka bir deÄiÅkene kopyalanabilir.
function selamVer() { // (1) oluÅtur
alert("Merhaba");
}
let func = selamVer; // (2) kopyala
func(); // Merhaba // (3) kopyası!
selamVer(); // Merhaba // kendisi.
Detayına bakılacak olursa:
1.(1) fonksiyon tanımlanır ve selamVer deÄiÅkenine atanır.
2. (2) bunu func deÄiÅkenine kopyalar.
Tekrardan hatırlatmak gerekirse: selamVer etrafında parantez bulunmamaktadır. EÄer func = selamVer() Åeklinde parantez ile yazılacak olsaydı,
func deÄiÅkenine atanan deÄer selamVer fonksiyonunun kendisi deÄil, bu fonksiyonun çıktısı olurdu.
- Fonksiyon bundan sonra
selamVer()vefunc()Åeklinde çaÄırılabilir.
Ayrıca ilk satır için fonksiyon ifadesi de kullanılabilirdi:
let selamVer = function() { ... };
let func = selamVer;
// ...
Her Åey aynı olduÄu gibi çalıÅırdı. Hatta neyin ne olduÄu daha açık deÄil mi?
Aklınıza bir soru takılabilir. Neden fonksiyon ifadesinin sonunda ; bulunmakta fakat fonksiyon tanımlada kullanılmıyor:
function selamVer() {
// ...
}
let selamVer = function() {
// ...
};
Cevap basit:
- Kod bloklarının sonunda
;e gerek yoktur. ÃrneÄinif{ ...},for{ ... },for { },function f{}vs. - Fonksiyon ifadesi bir ifade içinde kullanıldıÄından
let selamVer = ....;bir deÄerdir. Kod bloÄu deÄildir. Cümle sonlarında deÄer ne olursa olsun;kullanılması önerilir. Bundan dolayı;fonksiyon ifadesi ile alakalı deÄildir. Sadece tanımlamanın sonunu göstermek içindir. Tıpkı diÄer tanımlamalarda olduÄu gibi.
GeriçaÄrım Fonksiyonları ( Callback functions )
Fonksiyonların deÄer olarak paslanması ve fonksiyon ifadelerini biraz daha incelenmesi yerinde olur.
sor(soru,evet,hayir) adında 3 parametre alan bir fonksiyon yazılacak olursa:
soru- Soru cümlesi
evet- EÄer doÄru ise çalıÅacak fonksiyon
hayir- EÄer cevap yanlıŠise yapılacak fonksiyon
Fonksiyon soru sormalı, bu sorunun cevabına göre evet() veya hayir() fonksiyonları çaÄırılacaktır.
function sor(soru, evet, hayir) {
if (confirm(soru)) evet()
else hayir();
}
function tamamGoster() {
alert("Kabul ettiniz");
}
function iptalGoster() {
alert("ÃalıÅmasını durdurdunuz");
}
// kullanım: tamamGoster, iptalGoster fonksiyona parametre olarak gönderilmiÅtir.
sor("Kabul ediyor musunuz?", tamamGoster, iptalGoster);
Daha kısa yolunu yazmadan önce söylemek gerekir ki bu tür fonksiyonlar oldukça sıkça kullanılmaktadır. Gerçek hayattaki örnekleri ile yukarıdaki arasında fark ise gerçek hayatta basit bir confirm yerine daha karmaÅık olaylar için kullanılıyor olmalarıdır.
**sor fonksiyonunun argümanları callbacks veya geri çaÄrım fonksiyonları olarak adlandırılırlar.
Fikir fonksiyonu bizim baÅtan paslayıp ana fonksiyon içerisinde daha sonra duruma göre çaÄırılmasından kaynaklanmaktadır. ÃrneÄe bakarsanız tamamGoster âevetâ cevabı için geri çaÄrım fonksiyonuâdur.
Fonksiyon İfadesi kullanarak aynı fonksiyonu daha kısa bir Åekilde yazmak mümkün:
function sor(soru, evet, hayir) {
if (confirm(soru)) evet()
else hayir();
}
sor(
"Kabul Ediyor musun?",
function() { alert("Kabul ettin"); },
function() { alert("ÃalıÅmayı durdurdun."); }
);
GördüÄünüz gibi yukarıda fonksiyonlar doÄrudan sor(...) içerisinde tanımlandı. hiçbir isim kullanılmadıÄından dolayı. Böyle fonksiyonlara anonim veya anonymous fonksiyonlar denir. Bu fonksiyonlar sor fonksiyonu dıÅında ulaÅılabilir deÄillerdir(çünkü hiçbir deÄiÅkene atanmazlar).
Bu Åekilde isimsiz kullanım JavaScript içerisinde çok doÄaldır. Bu JavaScriptâin ruhunda var diyebiliriz.
Normal deÄerler örneÄin karakter dizisi ve sayılar veridir. Fonksiyon fiil olarak adlandırılabilir.
DeÄiÅkenler arasında paylaÅılabilir. İstendiÄi zaman çalıÅtırılabilir.
Fonksiyon ifadesi ile Fonksiyon tanımının karÅılaÅtırılması
EÄer Fonksiyon ifadesi ile fonksiyon tanımı arasındaki önemli farkları açıklamak gerekirse;
Yazım: Kodda neyin ne olduÄunu görme.
-
Fonksiyon Tanımlama: bir fonksiyon ana kod yapısında farklı bir cümle olarak tanımlanır.
// Fonksiyon Tanımlama function toplam(a, b) { return a + b; } -
Fonksiyon ifadesi: bir fonksiyon ifadenin içinde veya diÄer bir yazım yapısı ile ifade edilir.
Burada fonksiyon âatama ifadesinin =â saÄ tarafında tanımlanmıÅtır.
// Fonksiyon tanımı let toplam = function(a, b) { return a + b; };
Daha ince bir deÄiÅiklik ise fonksiyonun JavaScript motorunda ne zaman yaratılacaÄıdır.
Fonksiyon ifadesi kod çalıÅırken fonksiyona geldikten sonra kullanılır
ÃalıÅma atamanın saÄ tarafına geçince let sum = function..., bu noktadan sonra fonksiyon artık yaratıldı. Bundan böyle çaÄırılabilir veya baÅka bir deÄiÅkene atanabilir.
Fonksiyon tanımlama ise farklıdır.
Fonksiyon tanımlama tüm kod bloÄu içerisinde kullanılabilir
DiÄer bir deyiÅle, JavaScript kod bloÄunu çalıÅtırmaya hazırlandıÄında, önce fonksiyon tanımlamalarına bakar ve fonksiyonları yaratır. Bunu bir "baÅlatma evresi* olarak görmek mümkündür.
Tüm Fonksiyon tanımlamaları tamamlandıktan sonra çalıÅmaya devam eder.
Sonuç olarak, fonksiyon tanımı ile bu tanımdan önce çaÄırılabilir.
Ãrnek verecek olursak:
selamVer("Ahmet"); // Merhaba Ahmet
function selamVer(isim) {
alert( `Merhaba, ${isim}` );
}
Fonksiyon Tanımı olan selamVer JavaScriptâin hazırlanma evresinde tanımlanır. Kod çalıÅtıÄında kodun her yerinden bu koda eriÅmek mümkündür.
EÄer bu bir Fonksiyon tanımı olsaydı, çalıÅmazdı.
selamVer("Ahmet"); // hata!
let selamVer = function(adi) { // (*) büyü ortadan kalktı
alert( `Merhaba, ${adi}` );
};
Fonksiyon tanımı kendisine ulaÅtıÄında çalıÅır. Yani (*)'gelmeden tanımlanmıŠolmalıydı ki selamVer("Ahmet") çalıÅabilsin.
Fonksiyon tanımı eÄer kod bloÄunun içerisinde tanımlanırsa o bloÄun içerisinde her yerde kullanılabilir. Fakat dıÅarıda kullanılamaz.
Bazen sadece blok içinde o blokta kullanılacak yerel bir fonksiyon yaratmak daha kolay gelebilir. Fakat bu özellik problem yaratabilir.
ÃrneÄin, hosgeldin() fonksiyonunu yas deÄiÅkenine göre tanımlayalım. Böylece sonradan kullanılacak hale getirmiÅ oluruz.
AÅaÄıdaki kod çalıÅmayacaktır:
let yas = prompt("Kaç yaÅındasın?", 18);
// Åarta göre fonksiyon tanımlama
if (yas < 18) {
function merhaba() {
alert("Merhaba!");
}
} else {
function merhaba() {
alert("Merhabalar!");
}
}
// ...sonra kullan...
merhaba(); // Hata: merhaba() tanımlı deÄil.
Burada hata alınmasının nedeni Fonksiyon Tanımının if..else bloÄu içerisinde tanımlandıÄından dolayı dıÅarıdan çaÄırılamamasından dolayıdır.
DiÄer bir örnek:
let yas = 16; // yaÅ 16 diyelim.
if (yas < 18) {
merhaba(); // \ (çalıÅır)
// |
function merhaba() { // |
alert("Merhaba!"); // | Fonksiyon tanımı bu blok içirisinde her yerden çaÄırılabilir.
} // |
// |
merhaba(); // / (çalıÅır)
} else {
function merhaba() { // YaÅ 16 olduÄundan burası hiçbir zaman çalıÅmaz.
alert("Merhabalar!");
}
}
// Artık if bloÄunun dıÅında olduÄumuzdan dolayı burada fonksiyon tanımlarına ulaÅamayız.
merhaba(); // Error: merhaba tanımlı deÄil.
merhaba fonksiyonunu ifin dıÅında da kullanılabilir kılmak için ne yapılmalıdır?
DoÄru yaklaÅım Fonksiyon İfadesini kullanarak if in dıÅına bir merhaba deÄiÅkeni yaratıp ifin içinde bunun tanımını yapmak olabilir.
Artık beklenildiÄi gibi çalıÅır:
let yas = prompt("Kaç yaÅındasın?", 18);
let merhaba;
if (yas < 18) {
merhaba = function() {
alert("Merhaba!");
};
} else {
merhaba = function() {
alert("Merhabalar!");
};
}
merhaba(); // artık çalıÅır.
Veya ? ile de bu fonksiyon Åu Åekilde yazılabilir:
let yas = prompt("Kaç yaÅındasın?", 18);
let merhaba = (yas < 18) ?
function() { alert("Merhaba!"); } :
function() { alert("Merhabalar!"); };
merhaba(); // artık çalıÅır.
Ãncelikle eÄer fonksiyon tanımlamak istiyorsanız Fonksiyon Tanımı yazımını düÅünmeniz gerekmekte. Kodunuzu düzenlemeniz için size özgürlük saÄlar. Ãünkü fonksiyon tanımından önce fonksiyonu çaÄırmak mümkündür.
Ayrıca fonksiyon içerisinde function f(...){} ile araÅtırmak let f= function(....){..}e göre daha kolaydır. Fonksiyon Tanımı daha fazla göze batar.
Fakat eÄer Fonksiyon Tanımı iÅimize yaramaz ise(yukarıda örneÄin Fonksiyon ifadesini kullandık), bu durumda Fonksiyon İfadesi yöntemi kullanılmalıdır.
Ãzet
- Fonksiyonlar deÄerdir. Atanabilir, kopyalanabilir ve kodun herhangi bir yerinde tanımlanabilirler.
- EÄer tanımı ana kod içerisinde ayrı bir cümle ise buna âFonksiyon Tanımıâ denir.
- Fonksiyon tanımları kod çalıÅtırmadan önce iÅlenir. Böylece kodun her yerinden ulaÅılabilir olurlar.
- Fonksiyon tanımları ise kod çalıÅırken bu tanıma eriÅirse çalıÅır.
ÃoÄu zaman Fonksiyon Tanımı metodu tercih edilmelidir. Ãünkü bu Åekilde fonksiyon tanımlanmadan önce fonksiyon çaÄrısı yapmak mümkündür. Bu kodun daha düzenli tutulmasında yardımcı olur. Ayrıca daha okunabilirdir.
Fonksiyon ifadesi sadece Fonksiyon Tanımı yetersiz kalırsa kullanılmalıdır. Bu örnek daha önce yukarıda yapılmıÅtı.
Yorumlar
<code>kullanınız, birkaç satır eklemek için ise<pre>kullanın. EÄer 10 satırdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)