ÃoÄu zaman kod yazarken belirli bölümleri tekrarlama ihtiyacı duyulur.
ÃrneÄin kullanıcı hesabına giriÅ yaptıÄında veya çıktıÄında güzel görünümlü bir mesaj göstermek istenebilir.
Fonksiyonlar programın âyapı taÅıdırâ. Birçok defa bu fonksiyonlar çaÄırılarak tekrardan bu kodları yazmaktan kurtulunur.
Aslında var olan alert(mesaj), prompt(mesaj,varsayilan) ve confirm(soru) gibi fonksiyonları gördük. Fakat artık bunları yazmanın zamanı geldi.
Fonksiyon Tanımlama
Fonksiyon tanımlamak için function tanım kullanılır.
AÅaÄıdaki gibi görünür:
function mesajGoster() {
alert( 'Merhaba millet!' );
}
function kelimesi önce yazılır, ardından fonksiyonun adı ve sonra parametrelerin yazılacaÄı parantez açılır ve ihtiyaç duyulan parametreler yazılır, sonrasında ise kapatılıp süslü parantez ile fonksiyon gövdesine baÅlanır.
Yeni fonksyion ismiyle Åu Åekilde çaÄırılır: mesajGoster().
ÃrneÄin:
function mesajGoster() {
alert( 'Merhaba millet' );
}
mesajGoster();
mesajGoster();
mesajGoster() fonksiyonu kodu çalıÅtırır. Bu kod sonrasında Merhaba millet uyarısını iki defa göreceksiniz.
Bu örnek açıkça fonksiyonların ana amacını gösteriyor: Kod tekrarından kaçınma.
EÄer mesajı deÄiÅtirmek istersek bir yerde deÄiÅtirdiÄimizde bu fonksiyonu kullanan her yerde deÄiÅiklik olacaktır.
Yerel deÄiÅkenler
Fonksiyon içinde tanımlanan deÄiÅkene sadece o fonksiyon içerisinde eriÅilebilir.
ÃrneÄin:
function mesajGoster() {
let mesaj = "Merhaba! Ben Javascript"; // Yerel DeÄiÅken
alert( mesaj );
}
mesajGoster(); // Merhaba! Ben Javascript
alert( mesaj ); // <-- Hata! Bu deÄiÅken `mesajGoster` fonksiyonuna aittir.
DıŠDeÄiÅkenler
Fonksiyon, kendi dıÅında oluÅturulmuÅ deÄiÅkenlere eriÅebilir. ÃrneÄin:
let kullaniciAdi = 'Adem';
function mesajGoster() {
let mesaj = 'Hello, ' + kullaniciAdi;
alert(mesaj);
}
mesajGoster(); // Merhaba, Adem
Fonksiyon dıÅarıda bulunan deÄiÅkenlere tam kontrol saÄlar. Hatta modifiye edebilir.
ÃrneÄin:
let kullaniciAdi = 'Adem';
function mesajGoster() {
kullaniciAdi = "Yusuf"; // (1) dıÅarıda bulunan deÄiÅkenin deÄeri deÄiÅti.
let mesaj = 'Merhaba, ' + kullaniciAdi;
alert(mesaj);
}
alert( kullaniciAdi ); // Fonksiyon çaÄırılmadan Adem
mesajGoster();
alert( kullaniciAdi ); // fonksiyon çaÄırıldıktan sonra Yusuf,
DıÅarıda bulunan deÄiÅkenler eÄer yerel deÄiÅken yoksa kullanılırlar. Bazen eÄer let ile deÄiÅken oluÅturulmazsa karıÅıklık olabilir.
EÄer aynı isim ile fonksiyon içerisinde bir deÄiÅken oluÅturulmuÅ ise, fonksiyon içerisindeki deÄiÅkenin deÄeri düzenlenebilir. ÃrneÄin aÅaÄıda yerel bir deÄiÅken dıÅtaki deÄiÅken ile aynı isimdedir. Dolayısıyla yerel deÄiÅken düzenlenecektir. DıÅtaki deÄiÅken bundan etkilenmeyecektir.
let kullaniciAdi = 'Adem';
function mesajGoster() {
let kullaniciAdi = "Yusuf"; // yerel deÄiÅken tanımla
let mesaj = 'Merhaba, ' + kullaniciAdi; // Yusuf
alert(mesaj);
}
// buradaki fonksiyon kendi deÄiÅkenini yaratacak ve onu kullanacak.
mesajGoster();
alert( kullaniciAdi ); // Adem, deÄiÅmedi!!!, fonksiyon dıÅarıda bulunan deÄiÅkene eriÅmedi.
Fonksiyonların dıÅına yazılan her deÄiÅken, yukarıda bulunan kullaniciAdi gibi, evrensel veya global deÄiÅken olarak adlandırılırlar.
Global deÄiÅkenlere her fonksiyon içerisinden eriÅilebilir.(Yerel deÄiÅkenler tarafından aynı isimle bir deÄiÅken tanımlanmamıÅsa)
Genelde fonksiyonlar yapacakları iÅe ait tüm deÄiÅkenleri tanımlarlar, global deÄiÅkenler ise sadece proje seviyesinde bilgi tutarlar, çünkü proje seviyesinde bilgilerin projenin her yerinden eriÅilebilir olması oldukça önemlidir. Modern kodda az veya hiç global deÄer olmaz. ÃoÄu fonksiyona ait deÄiÅkenlerdir.
Parametreler
Parametrelere isteÄe baÄlı olarak veri paslanabilir. Bunlara fonksiyon argümanları da denir.
AÅaÄıdaki fonksiyon iki tane parametreye sahiptir. gonderen ve metin
function mesajGoster(gonderen, metin) { // argümanlar: gonderen, metin
alert(gonderen + ': ' + metin);
}
mesajGoster('Ahmet', 'Merhaba!'); // Ahmet: Merhaba! (*)
mesajGoster('Mehmet', "Naber?"); // Mehmet: Naber? (**)
EÄer fonksiyonlar (*) ve (**) deki gibi yazılırsa doÄrudan fonksiyonda gonderen ve metin yerel deÄiÅkenlerine atanırlar. Sonrasında fonksiyon bunları kullanabilir.
AÅaÄıda gonderen deÄiÅkeni fonksiyona paslanmakta. Dikkat ederseniz fonksiyon içerisinde gonderen deÄiÅse bile bu dıÅarıda bulunan deÄiÅkeni etkilememekte. Ãünkü fonksiyon bu deÄiÅkenin her zaman kopyasını kullanır:
function mesajGoster(gonderen,metin) {
gonderen = '*' + gonderen + '*'; // "gonderen" biraz daha güzel hale getirildi.
alert( gonderen + ': ' + metin );
}
let gonderen = "Mahmut";
mesajGoster(gonderen, "Merhaba"); // *Mahmut*: Merhaba
// "gonderen" deÄiÅkeninin deÄeri sadece fonksiyon içerisinde deÄiÅti. Ãünkü bu deÄiÅken paslandıÄında fonksiyon yerel bir kopyası üzerinde çalıÅır
alert( gonderen ); // Mahmut
Varsayılan DeÄerler
EÄer fonksiyon argümanına bir deÄer gönderilmemiÅse fonksiyon içerisinde bu deÄiÅken undefined olur.
ÃrneÄin mesajGoster(gonderen,metin) fonksiyonu tek argüman ile de çaÄırılabilir.
mesajGoster("Mahmut");
Bu bir hata deÄildir. Fonksiyon eÄer bu Åekilde çaÄırılırsa, yani metin yoksa, metin == undefined varsayılır. Yukarıdaki fonksiyon çaÄırıldıÄında sonuç âMahmut: undefinedâ olacaktır.
EÄer âvarsayılanâ olarak metin deÄeri atamak istiyorsanız, = iÅareti ile tanımlamanız gerekmekte.
function mesajGoster(gonderen, metin = "metin gönderilmedi") {
alert(gonderen + ": " + metin );
}
mesajGoster("Mahmut"); // Mahmut: metin gönderilmedi
EÄer metin deÄeri paslanmazsa, "metin gönderilmedi" çıktısı alınır.
"metin gönderilmedi" Åu anda karakter dizisidir. Fakat daha karmaÅık yapılar olabilir. Sadece parametre gönderilmez ise bu deÄer atanır. AÅaÄıdaki kullanım da pekala doÄrudur.
function mesajGoster(gonderen, metin = digerFonksiyon()) {
// eÄer metin gönderilmez ise digerFonksiyon çalıÅır ve sonucu "metin" deÄiÅkenine atanır.
}
Eski tip JavaScript varsayılan parametreleri desteklememekteydi. Bundan dolayı farklı yöntemler geliÅtirdi. EÄer eskiden yazılmıŠkodları okursanız bu kodlara rastlayabilirsiniz.
ÃrneÄin doÄrudan undefined kontrolü:
function mesajGoster(gonderen, metin) {
if (metin === undefined) {
text = 'metin gönderilmedi';
}
alert( gonderen + ": " + metin );
}
â¦Veya || operatörü:
function mesajGoster(gonderen, metin) {
// eÄer metin yanlıŠdeÄer ise( bu durumda undefined yanlıŠdeÄerdir hatırlarsanız ) 'metin gönderilmedi' ata.
text = text || 'metin gönderilmedi';
...
}
DeÄer döndürme
Fonksiyon çaÄırıldıÄı yere deÄer döndürebilir.
En basit örnek iki deÄeri toplayan bir fonksiyon olabilir.
function toplam(a, b) {
return a + b;
}
let sonuc = toplam(1, 2);
alert( sonuc ); // 3
return fonksiyon içerisinde her yerde kullanılabilir. Kod return satırına eriÅtiÄinde fonksiyon durur ve deÄer fonksiyonun çaÄırıldıÄı yere geri gönderilir.
Bir fonksiyon içerisinde birden fazla return fonksiyonu da olabilir.
function yasKontrolu(yas) {
if (yas > 18) {
return true;
} else {
return confirm('Ebevenylerinin izni var mı?');
}
}
let yas = prompt('Kaç yaÅındasın?', 18);
if ( yasKontrolu(yas) ) {
alert( 'İzin verildi' );
} else {
alert( 'Reddedildi' );
}
return deÄer döndürmek zorunda deÄildir. Bu fonksiyondan anında çıkmayı saÄlar.
ÃrneÄin:
function filmGoster(age) {
if ( !yasKontrolu(yas) ) {
return;
}
alert( "Filmleri izleyebilirsin" ); // (*)
// ...
}
Yukarıdaki kodda eÄer yasKontrolu(yas) false döndürür ise filmGoster fonksiyonu alerte eriÅemeyecektir.
undefined döndürürEÄer bir fonksiyon deÄer döndürmüyor ise bu fonksiyon undefined döndürüyor ile aynı anlama gelir.
function biseyYapma() { /* boÅ */ }
alert( biseyYapma() === undefined ); // true
BoŠdöndüren return, return undefined ile aynıdır.
function biseyYapma() {
return;
}
alert( biseyYapma() === undefined ); // true
return ve deÄer arasına hiçbir zaman satır eklemeyinUzun return ifadelerinde, yeni bir satırda yazmak size kullanıÅlı gelebilir, örneÄin aÅaÄıdaki gibi:
return
(bazı + uzun + ifade + veya + baska + birsey * f(a) + f(b))
Bu çalıÅmaz, çünkü JavaScript return kelimesinden sonra ; varsayar ve undefined döner. Bu aÅaÄıdaki ifade ile aynıdır:
return;
(bazı + uzun + ifade + veya + baska + birsey * f(a) + f(b))
Bundan dolayı, tam olarak boÅ return olur. Geri döndüreceÄimiz deÄer ile return aynı satırda olmalıdır.
Fonksiyonu isimlendirme
Fonksiyonlar eylemdir. Bundan dolayı isimleri yüklem olmalıdır. Net olmalı ve fonksiyonun ne iÅe yaradıÄını ifade edebilmelidir. Böylece kim ki kodu okur, ne yazıldıÄına dair bir fikri olur.
Genel itibari ile eylemi tanımlayan ön ek kullanmak iyi bir yöntemdir. Bu ön ekler ile ilgili birlikte kod yazdıÄınız kiÅiler ile uyum içerisinde olmalısınız.
ÃrneÄin "show" fonksiyonu her zaman bir Åeyleri gösterir.
Fonksiyonlar Åöyle baÅlayabilir.
"getâ¦"â deÄer döndürür,"calcâ¦"â bir Åeyler hesaplar,"createâ¦"â bir Åeyler yaratır,"checkâ¦"â bir Åeyleri kontrol eder ve boolean döndürür.
Böyle isimlere örnek:
Not: İngilizceâde bu daha kolay önce eylemi yazıyorlar. Türkçeâde fiil genelde sonda olduÄundan dolayı sıkıntı yaÅanmaktadır. Fonksiyonlarınızı adlandırırken İngilizce adlandırırsanız okunması daha kolay olacaktır.
sendMessage(..) // mesaj gönderir
getAge(..) // yaÅı döndürür
calcSum(..) // toplamı hesaplar ve geri döndürür.
createForm(..) // form oluÅturur ve genelde geri döndürür.
checkPermission(..) // izni kontor eder. true/false
Ãn ek ile fonksiyonlar bir anlamda ipucu verir ve ne tür deÄerler dönmesi gerektiÄini anlatır.
Bir fonksiyon sadece isminin tanımladıÄı iÅi yapmalı.
İki birbirinden farklı eylem çoÄu zaman iki fonksiyon ile yazılmalıdır, birlikte çaÄrılsalar bile ( bu durumda 3. bir fonksiyon bunları çaÄırmalıdır )
Bu kurallar Åu Åekilde bozulabilir:
getAgeâ EÄer bu fonksiyon içeridealertile yaÅ gösteriyor ise yanlıŠolur. Bu fonksiyonun sadece yaÅı alıp döndürmesi gerekmekte.createFormâ EÄer dökümanı deÄiÅtiriyorsa veya forma bir Åey ekliyorsa yanlıŠolur. ( Sadece formu yaratmalı ve geri dönmelidir )checkPermissionâ EÄerizin verildi/reddedildigibi mesajları bu fonksiyon gösterirse yanlıŠolur. Sadece kontrol etmeli ve geri dönmelidir.
Bu örnekler genel olarak öneklerin nasıl tahmin edilmesi gerektiÄini gösterir. Bunların ne anlama geleceÄi siz ve takımınıza kalmıÅtır. Belki sizin kodunuz için farklı bir Åekilde davranması gayet doÄal olabilir. Fakat yine de ön eklere ait bir anlamlandırmanız olmalıdır. Ãn ek ne yapabilir ne yapamaz vs. Tüm aynı önekli fonksiyonlar sizin koyduÄunuz kurala uymalı ve tüm takım bu kuralları biliyor olmalıdır.
Ãokça kullanılan fonksiyonlar genelde aÅırı derece kısa isimlere sahip olurlar.
ÃrneÄin, jQuery kütüphanesi $ fonksiyonu ile tanımlanır. LoDash kütüphanesi de keza kendine has fonksiyon _ kullanır.
Bunlar istisnadır. Genel olarak fonksiyon isimleri kısa ve açıklayıcı olmalıdır.
Fonksiyonlar == Yorumlar
Fonksiyonlar kısa olmalı ve sadece bir Åeyi yapmalıdırlar. EÄer uzun ise bu durumda ayırıp yeni bir fonksiyon yapmanız daha iyi olabilir. Bazen bu kuralı takip etmek zor olabilir. Fakat kesinlikle iyi bir Åeydir.
Farklı fonksiyon daha kolay bir Åekilde çalıÅması kontrol edilebilir. VarlıÄı harika bir yorumdur.
ÃrneÄin, aÅaÄıdaki iki asalGoster(n) fonksiyonunu karÅılaÅtırın. Asal Sayı
İlk tanım label kullanıyor:
function asalGoster(n) {
sonrakiAsal: for (let i = 2; i < n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue sonrakiAsal;
}
alert( i ); // asal sayı
}
}
İkinci tip ise asalMi(n) adında ikinci bir fonksiyon ile asal olup olmama durumunu kontrol ediyor.
function asalGoster(n) {
for (let i = 2; i < n; i++) {
if (!asalMi(i)) continue;
alert(i); // asal sayı
}
}
function asalMi(n) {
for (let i = 2; i < n; i++) {
if ( n % i == 0) return false;
}
return true;
}
İkinci örnek anlaÅılması daha kolay deÄil mi? asalMi gibi fonksiyon isimleri yerine bazıları buna kendi kendini açıklayan demektedir.
Fonksiyonlar eÄer tekrar kullanmayacaÄımızı bilsek bile oluÅturulabilir. Kodu daha okunabilir yaparlar.
Ãzet
Bir fonksiyonun tanımı aÅaÄıdaki gibidir.
function fonksiyon ismi(parametreler, virgül , ile, ayrilirlar) {
/* code */
}
- Fonksiyona paslanan parametreler yerel deÄiÅken olarak fonksiyon içerisinde kopyalanırlar.
- Fonksiyon dıÅarıdaki deÄiÅkene eriÅebilir. Fakat içeride yaratılmıŠbir deÄiÅken dıÅarıda kullanılamaz.
- Fonksiyon deÄer döndürebilir. EÄer döndürmezse
undefinedolarak tanımlanır.
Kodun daha anlaÅılır ve okunabilir olması için, fonksiyonlar içerisinde yerel deÄiÅken kullanılması önerilir. DıŠdeÄiÅkenler kullanılması önerilmez.
EÄer fonksiyon parametre ile deÄer alır ve bu deÄer üzerinde çalıÅıp deÄer geri döndürürse anlaÅılırlıÄı artar. Fakat eÄer fonksiyon hiçbir parametre almadan sadece dıÅarıdaki deÄiÅkenleri deÄiÅtiriyor ise kodun anlaÅılırlıÄı büyük ölçüde azalır.
Fonksiyon isimlendirme:
- Bir isim fonksiyonun ne iÅe yaradıÄını açıklayabiliyor olmalıdır. İyi bir isim fonksiyonun okunmadan ne iÅ yaptıÄına dair fikir verir.
- Fonksiyon bir fiili yerine getirdiÄinden, fonksiyon isimleri yüklem olmalıdır.
- Bunlar için ön ek kullanabilirsiniz. Türkçe sondan eklemeli bir dil olduÄundan dolayı fonksiyon ekleri sona gelmektedir. ÃrneÄin
asalGoster, bu tip kullanım aslında okunurluk açısından pekte iyi deÄil benim kanaatimce. Ãünkü okurken önce ne yaptıÄını anlaÅılmıyor. Fakat İngilizce örneÄine bakarsanızshowPrime, burada önce ne yaptıÄını söylüyor. Farzedin ki birçok fonksiyonunuz var ve okuduÄunuzda önce ne iÅ yaptıÄını bilmek bunları filtrelemenizde size yardımcı olacaktır. - Ãrnek kaç tane ek ,
create...,show...,get...,check...vs.
Fonksiyonlar kod yazarken kullanılan ana yapılardır. Artık temellerini anlaÅıldıÄına göre kullanılmaya baÅlanabilir. Fakat sadece temellerinin gösterildiÄini bilmekte fayda var. İleride defalarca fonksiyonlar konusuna geri dönülecektir.
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)