Logo

Bölüm 5: Fonksiyonlar ve Kapsamlar

15 Haziran 2025
6 dk okuma süresi
fonksiyonlar-kapsamlar

Fonksiyonlar Nedir?

Fonksiyonlar, belirli bir görevi yerine getiren, yeniden kullanılabilir kod bloklarıdır. JavaScript’te fonksiyonlar “birinci sınıf vatandaş” olarak kabul edilir, yani değişkenlere atanabilir, başka fonksiyonlara parametre olarak geçilebilir ve fonksiyonlardan döndürülebilir.

Neden Fonksiyon Kullanırız?

  • Kod Tekrarını Önler: Aynı işlemi birden fazla yerde yapabiliriz
  • Modülerlik: Kodu küçük, yönetilebilir parçalara böler
  • Okunabilirlik: Kodun ne yaptığı daha açık olur
  • Test Edilebilirlik: Her fonksiyon ayrı ayrı test edilebilir
  • Hata Ayıklama: Problemleri daha kolay buluruz

Fonksiyon Tanımlama Yöntemleri

1. Function Declaration (Fonksiyon Bildirimi)

function selamla(isim) {
    return `Merhaba ${isim}!`;
}
 
// Kullanım
console.log(selamla('Furkan')); // "Merhaba Furkan!"
 
// Hoisting - tanımlamadan önce çağırılabilir
console.log(erkenSelamla('Test')); // Çalışır!
 
function erkenSelamla(isim) {
    return `Erken merhaba ${isim}!`;
}

2. Function Expression (Fonksiyon İfadesi)

// Anonim fonksiyon
let carpma = function(a, b) {
    return a * b;
};
 
// İsimli fonksiyon ifadesi
let bolme = function bolmeIslemi(a, b) {
    if (b === 0) {
        console.log('Sıfıra bölünemez!');
        return null;
    }
    return a / b;
};
 
console.log(carpma(5, 3));     // 15
console.log(bolme(10, 2));     // 5

3. Arrow Functions (Ok Fonksiyonları) - ES6+

// Temel arrow function
let topla = (a, b) => {
    return a + b;
};
 
// Tek ifade için kısa yazım
let kare = x => x * x;
let selamVer = () => 'Merhaba Dünya!';
 
// Parametre sayısına göre
let tekParam = x => x * 2;           // Tek parametre, parantez opsiyonel
let cokParam = (x, y, z) => x + y + z; // Çok parametre, parantez gerekli
let paramYok = () => Math.random();    // Parametre yok, parantez gerekli
 
console.log(kare(5));           // 25
console.log(tekParam(10));      // 20
console.log(cokParam(1, 2, 3)); // 6
Ipucu

Arrow Function Avantajları: Daha kısa yazım, lexical this binding (gelişmiş konularda önemli). Callback fonksiyonlarda çok kullanışlı!

Parametreler ve Argumentlar

Temel Parametre Kullanımı

function kullaniciBilgisi(isim, yas, sehir) {
    console.log(`İsim: ${isim}`);
    console.log(`Yaş: ${yas}`);
    console.log(`Şehir: ${sehir}`);
}
 
kullaniciBilgisi('Furkan', 25, 'İstanbul');
 
// Eksik parametre - undefined olur
kullaniciBilgisi('Ahmet', 30); // sehir = undefined

Varsayılan Parametreler (ES6+)

function selamla(isim = 'Misafir', dil = 'tr') {
    const mesajlar = {
        tr: `Merhaba ${isim}!`,
        en: `Hello ${isim}!`,
        fr: `Bonjour ${isim}!`
    };
    
    return mesajlar[dil] || mesajlar.tr;
}
 
console.log(selamla());                    // "Merhaba Misafir!"
console.log(selamla('Furkan'));            // "Merhaba Furkan!"
console.log(selamla('John', 'en'));        // "Hello John!"

Rest Parameters (Kalan Parametreler)

function topla(...sayilar) {
    let toplam = 0;
    for (let sayi of sayilar) {
        toplam += sayi;
    }
    return toplam;
}
 
console.log(topla(1, 2, 3));           // 6
console.log(topla(1, 2, 3, 4, 5));     // 15
console.log(topla(10));                // 10
 
// İlk parametre ayrı, geri kalanı dizi
function ilkVeGeriKalan(ilk, ...geriKalan) {
    console.log('İlk:', ilk);
    console.log('Geri kalan:', geriKalan);
}
 
ilkVeGeriKalan('a', 'b', 'c', 'd'); 
// İlk: a
// Geri kalan: ['b', 'c', 'd']

Destructuring ile Parametreler

// Obje destructuring
function kullaniciOlustur({isim, yas, email, sehir = 'Belirtilmemiş'}) {
    return {
        id: Date.now(),
        isim,
        yas,
        email,
        sehir,
        olusturulma: new Date()
    };
}
 
let yeniKullanici = kullaniciOlustur({
    isim: 'Furkan',
    yas: 25,
    email: '[email protected]'
});
 
console.log(yeniKullanici);
 
// Dizi destructuring
function koordinatIslemi([x, y, z = 0]) {
    return {
        x: x,
        y: y,
        z: z,
        mesafe: Math.sqrt(x*x + y*y + z*z)
    };
}
 
console.log(koordinatIslemi([3, 4]));     // z = 0
console.log(koordinatIslemi([3, 4, 5]));  // z = 5

Return (Geri Dönüş) Değerleri

Temel Return Kullanımı

function dikdortgenAlan(uzunluk, genislik) {
    return uzunluk * genislik;
}
 
function cemberAlan(yaricap) {
    return Math.PI * yaricap * yaricap;
}
 
let alan1 = dikdortgenAlan(5, 3);  // 15
let alan2 = cemberAlan(4);         // ~50.27
 
// Return yoksa undefined döner
function mesajYazdir(mesaj) {
    console.log(mesaj);
    // return yok
}
 
let sonuc = mesajYazdir('Test'); // undefined

Çoklu Return Değerleri

// Obje döndürme
function islemler(a, b) {
    return {
        toplam: a + b,
        fark: a - b,
        carpim: a * b,
        bolum: b !== 0 ? a / b : null
    };
}
 
let sonuclar = islemler(10, 5);
console.log(sonuclar); // {toplam: 15, fark: 5, carpim: 50, bolum: 2}
 
// Dizi döndürme
function minMax(sayilar) {
    return [Math.min(...sayilar), Math.max(...sayilar)];
}
 
let [minimum, maksimum] = minMax([3, 1, 9, 2, 8]);
console.log(`Min: ${minimum}, Max: ${maksimum}`); // Min: 1, Max: 9

Erken Return (Guard Clauses)

function yasiKategoriAl(yas) {
    // Geçersiz girdi kontrolü
    if (typeof yas !== 'number' || yas < 0) {
        return 'Geçersiz yaş';
    }
    
    // Erken return'ler - temiz kod
    if (yas < 13) return 'Çocuk';
    if (yas < 18) return 'Genç';
    if (yas < 65) return 'Yetişkin';
    return 'Yaşlı';
}
 
console.log(yasiKategoriAl(25));  // "Yetişkin"
console.log(yasiKategoriAl(-5));  // "Geçersiz yaş"

Scope (Kapsam) Kavramı

Global Scope

// Global değişken - her yerden erişilebilir
let globalDegisken = 'Ben globalim';
 
function test1() {
    console.log(globalDegisken); // Erişebilir
}
 
function test2() {
    globalDegisken = 'Değiştirildi'; // Değiştirilebilir
}
 
test1(); // "Ben globalim"
test2();
test1(); // "Değiştirildi"

Function Scope

function fonksiyonKapsami() {
    let lokalDegisken = 'Ben lokali̧m';
    var eskiDeğisken = 'Ben varım';
    
    console.log(lokalDegisken); // Çalışır
    
    if (true) {
        let blokDegisken = 'Ben blok içindeyim';
        var fonksiyonGeneli = 'Ben fonksiyon genelindeyim';
        
        console.log(blokDegisken); // Çalışır
    }
    
    // console.log(blokDegisken); // Hata! Tanımsız
    console.log(fonksiyonGeneli); // Çalışır (var hoisting)
}
 
// console.log(lokalDegisken); // Hata! Fonksiyon dışından erişilemez

Lexical Scope (Sözcüksel Kapsam)

let disaridaki = 'dışarıdaki değer';
 
function disFonksiyon() {
    let disDegisken = 'dış fonksiyon değişkeni';
    
    function icFonksiyon() {
        let icDegisken = 'iç fonksiyon değişkeni';
        
        // İç fonksiyon tüm dış kapsamlara erişebilir
        console.log(icDegisken);    // ✅ Erişebilir
        console.log(disDegisken);   // ✅ Erişebilir
        console.log(disaridaki);    // ✅ Erişebilir
    }
    
    icFonksiyon();
    // console.log(icDegisken); // ❌ Erişemez
}
 
disFonksiyon();

Closure (Kapanış)

// Basit closure örneği
function disFonksiyon(x) {
    // Bu değişken closure ile korunur
    return function icFonksiyon(y) {
        return x + y; // x'e hala erişebiliyor
    };
}
 
let topla5 = disFonksiyon(5);
console.log(topla5(3)); // 8 (5 + 3)
 
// Pratik closure örneği - Sayaç
function sayacOlustur() {
    let sayac = 0;
    
    return {
        artir: function() {
            sayac++;
            return sayac;
        },
        azalt: function() {
            sayac--;
            return sayac;
        },
        deger: function() {
            return sayac;
        }
    };
}
 
let benimSayacim = sayacOlustur();
console.log(benimSayacim.artir());   // 1
console.log(benimSayacim.artir());   // 2
console.log(benimSayacim.azalt());   // 1
console.log(benimSayacim.deger());   // 1
 
// Farklı sayaç
let baskaasayac = sayacOlustur();
console.log(baskaasayac.artir());    // 1 (bağımsız)

Higher-Order Functions (Yüksek Dereceli Fonksiyonlar)

Fonksiyon Parametre Olarak

function islemYap(a, b, islem) {
    return islem(a, b);
}
 
function topla(x, y) { return x + y; }
function carp(x, y) { return x * y; }
 
console.log(islemYap(5, 3, topla)); // 8
console.log(islemYap(5, 3, carp));  // 15
 
// Anonim fonksiyon ile
console.log(islemYap(10, 2, function(a, b) {
    return a / b;
})); // 5
 
// Arrow function ile
console.log(islemYap(8, 3, (a, b) => a % b)); // 2

Fonksiyon Döndüren Fonksiyonlar

function carpanOlustur(carpan) {
    return function(sayi) {
        return sayi * carpan;
    };
}
 
let ikiKati = carpanOlustur(2);
let ucKati = carpanOlustur(3);
 
console.log(ikiKati(5));  // 10
console.log(ucKati(4));   // 12
 
// Daha karmaşık örnek
function filtreOlustur(kriter) {
    return function(dizi) {
        return dizi.filter(kriter);
    };
}
 
let ciftFiltralayici = filtreOlustur(x => x % 2 === 0);
let buyukFiltralayici = filtreOlustur(x => x > 10);
 
let sayilar = [1, 2, 3, 4, 15, 20, 25];
console.log(ciftFiltralayici(sayilar));    // [2, 4, 20]
console.log(buyukFiltralayici(sayilar));   // [15, 20, 25]

Pratik Örnekler

Kişi Yönetim Sistemi

// Kişi oluşturucu fonksiyon
function kisiOlustur(isim, soyisim, yas, email) {
    return {
        isim,
        soyisim,
        yas,
        email,
        tamIsim: function() {
            return `${this.isim} ${this.soyisim}`;
        },
        yasKategorisi: function() {
            if (this.yas < 18) return 'Çocuk';
            if (this.yas < 65) return 'Yetişkin';
            return 'Yaşlı';
        },
        emailGecerli: function() {
            return this.email.includes('@') && this.email.includes('.');
        }
    };
}
 
// Kişi listesi yöneticisi
function kisiListesiOlustur() {
    let kisiler = [];
    
    return {
        ekle: function(kisi) {
            if (kisi.emailGecerli()) {
                kisiler.push(kisi);
                return true;
            }
            return false;
        },
        
        listele: function() {
            return kisiler.map(kisi => ({
                tamIsim: kisi.tamIsim(),
                yas: kisi.yas,
                kategori: kisi.yasKategorisi(),
                email: kisi.email
            }));
        },
        
        ara: function(arama) {
            return kisiler.filter(kisi => 
                kisi.tamIsim().toLowerCase().includes(arama.toLowerCase())
            );
        },
        
        yasinaGore: function(minYas, maxYas) {
            return kisiler.filter(kisi => 
                kisi.yas >= minYas && kisi.yas <= maxYas
            );
        }
    };
}
 
// Kullanım
let kisiListesi = kisiListesiOlustur();
 
let furkan = kisiOlustur('Furkan', 'Çelik', 25, '[email protected]');
let ahmet = kisiOlustur('Ahmet', 'Yılmaz', 30, '[email protected]');
 
kisiListesi.ekle(furkan);
kisiListesi.ekle(ahmet);
 
console.log(kisiListesi.listele());
console.log(kisiListesi.ara('Furkan'));

Hesap Makinesi Sistemi

function hesapMakinesiOlustur() {
    let gecmis = [];
    
    function islemKaydet(islem, sonuc) {
        gecmis.push({
            islem,
            sonuc,
            tarih: new Date().toLocaleString('tr-TR')
        });
    }
    
    return {
        topla: function(a, b) {
            let sonuc = a + b;
            islemKaydet(`${a} + ${b}`, sonuc);
            return sonuc;
        },
        
        cikar: function(a, b) {
            let sonuc = a - b;
            islemKaydet(`${a} - ${b}`, sonuc);
            return sonuc;
        },
        
        carp: function(a, b) {
            let sonuc = a * b;
            islemKaydet(`${a} × ${b}`, sonuc);
            return sonuc;
        },
        
        bol: function(a, b) {
            if (b === 0) {
                let hata = 'Sıfıra bölünemez!';
                islemKaydet(`${a} ÷ ${b}`, hata);
                return hata;
            }
            let sonuc = a / b;
            islemKaydet(`${a} ÷ ${b}`, sonuc);
            return sonuc;
        },
        
        us: function(taban, us) {
            let sonuc = Math.pow(taban, us);
            islemKaydet(`${taban}^${us}`, sonuc);
            return sonuc;
        },
        
        gecmisGoster: function() {
            console.log('İşlem Geçmişi:');
            console.log('='.repeat(40));
            gecmis.forEach((kayit, indeks) => {
                console.log(`${indeks + 1}. ${kayit.islem} = ${kayit.sonuc} (${kayit.tarih})`);
            });
        },
        
        gecmisTemizle: function() {
            gecmis = [];
            console.log('Geçmiş temizlendi.');
        }
    };
}
 
// Kullanım
let calc = hesapMakinesiOlustur();
 
console.log(calc.topla(5, 3));      // 8
console.log(calc.carp(4, 7));       // 28
console.log(calc.bol(10, 0));       // Sıfıra bölünemez!
console.log(calc.us(2, 3));         // 8
 
calc.gecmisGoster();

Pratik Egzersizler

Egzersiz 1: Öğrenci Not Sistemi

function ogrenciSistemiOlustur() {
    // 1. Öğrenci ekleme fonksiyonu
    // 2. Not ekleme fonksiyonu
    // 3. Ortalama hesaplama
    // 4. Harf notu belirleme
    // 5. Sınıf raporu oluşturma
    
    // Bu sistemi tamamlayın
}

Egzersiz 2: Basit Banka Sistemi

function bankaHesabi(baslangicBakiye = 0) {
    // 1. Para yatırma (yatir)
    // 2. Para çekme (cek)
    // 3. Bakiye sorgulama (bakiye)
    // 4. İşlem geçmişi (gecmis)
    // 5. Faiz hesaplama (faizHesapla)
    
    // Closure kullanarak güvenli bir sistem oluşturun
}

Egzersiz 3: Görev Yöneticisi

function gorevYoneticisiOlustur() {
    // 1. Görev ekleme (ekle)
    // 2. Görev tamamlama (tamamla)
    // 3. Görev silme (sil)
    // 4. Filtreleme (tamamlananlar, bekleyenler)
    // 5. Öncelik sıralaması
    
    // Her görev: {id, baslik, aciklama, tamamlandi, oncelik, tarih}
}
Uyarı

Önemli Not: Arrow function’lar kendi this bağlamına sahip değildir. Obje metodları için function declaration kullanmayı tercih edin veya arrow function’ların this davranışını öğrenin.

Sıradaki Bölüm

Bir sonraki bölümde DOM Manipülasyonu öğreneceksiniz. JavaScript’le HTML elementlerini nasıl seçeceğinizi, değiştireceğinizi ve dinamik web sayfaları oluşturacağınızı keşfedeceksiniz.

Öğrendikleriniz:

  • ✅ Function declaration, expression ve arrow function’ları
  • ✅ Parametreler, default values ve rest parameters
  • ✅ Return değerleri ve çoklu return teknikleri
  • ✅ Scope, closure ve lexical scoping kavramları
  • ✅ Higher-order functions ve callback’ler
  • ✅ Pratik fonksiyon tasarım prensipleri

Artık JavaScript’te kodunuzu düzenli, yeniden kullanılabilir fonksiyonlara ayırabiliyorsunuz! Sırada bu fonksiyonları kullanarak web sayfalarını dinamik hale getirmeyi öğrenmek var. 🎯