20 Nisan 2016 Çarşamba

Javascript'de Fonksiyonlar

Merhaba Webkolog Takipçileri!

Bugün JavaScript'in kalbi diyebileceğimiz bir konuya dalıyoruz: fonksiyonlar! Fonksiyonlar, kodunuzu organize etmenizi, tekrar kullanılabilir hale getirmenizi ve programlarınızın daha modüler olmasını sağlayan temel yapı taşlarıdır. İster basit bir hesaplama yapın ister karmaşık bir etkileşim tasarlayın, fonksiyonlar her zaman yanınızda. Hadi, JavaScript fonksiyonlarının büyüleyici dünyasına adım atalım!


Fonksiyon Nedir ve Neden Kullanırız?

Basitçe söylemek gerekirse, bir fonksiyon belirli bir görevi yerine getiren, bir araya getirilmiş bir dizi ifadedir. Bir fonksiyonu tanımladığınızda, onu daha sonra istediğiniz zaman, istediğiniz kadar çağırabilirsiniz. Bu, kod tekrarını azaltır (DRY - Don't Repeat Yourself prensibi) ve programınızı daha okunabilir, yönetilebilir ve hata ayıklaması daha kolay hale getirir.


Fonksiyon Tanımlama Yöntemleri

JavaScript'te fonksiyon tanımlamanın birkaç farklı yolu vardır:

1. Fonksiyon Bildirimi (Function Declaration)

Bu, en yaygın ve geleneksel yöntemdir. Fonksiyon adıyla birlikte function anahtar kelimesi kullanılır.


    function selamla() {
        console.log("Merhaba Webkolog!");
    }

    selamla(); // Fonksiyonu çağırma

Fonksiyon bildirimleri "hoisting" özelliğine sahiptir, yani kodda tanımlandıkları yerden önce bile çağrılabilirler.

2. Fonksiyon İfadesi (Function Expression)

Fonksiyonu bir değişkene atayarak da tanımlayabiliriz. Bu durumda fonksiyona bir isim vermek zorunda değiliz (anonim fonksiyon).


    const toplama = function(a, b) {
        return a + b;
    };

    console.log(toplama(5, 3)); // 8

Fonksiyon ifadeleri hoisting'e tabi değildir; tanımlandıkları satırdan sonra çağrılmalıdır.

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

ES6 (ECMAScript 2015) ile birlikte gelen ok fonksiyonları, daha kısa ve daha sade bir sözdizimine sahiptir, özellikle basit fonksiyonlar için. Ayrıca this anahtar kelimesini farklı ele almasıyla da önemlidir.

  • Tek parametreli ve tek satırlık ifade: Parantez ve return anahtar kelimesi atlanabilir.
    
                const kareAl = num => num * num;
                console.log(kareAl(4)); // 16
            
  • Birden fazla parametre veya çok satırlık ifadeler: Parametreler parantez içine alınmalı ve birden fazla ifade için süslü parantez {} kullanılmalı. return anahtar kelimesi manuel olarak yazılmalı.
    
                const farkBul = (sayi1, sayi2) => {
                    let fark = sayi1 - sayi2;
                    return Math.abs(fark); // Mutlak değeri döndürür
                };
                console.log(farkBul(10, 5)); // 5
                console.log(farkBul(5, 10)); // 5
            

Fonksiyon Parametreleri ve Argümanları

Fonksiyonlar, kendilerine dışarıdan bilgi göndermemizi sağlayan parametreler alabilir. Fonksiyonu çağırdığımızda gönderdiğimiz değerlere ise argüman denir.

Varsayılan Parametreler (ES6+)

Bir parametreye değer gönderilmediğinde kullanılacak varsayılan bir değer belirleyebilirsiniz.


    function selamVer(isim = "Misafir") {
        console.log(`Merhaba, ${isim}!`);
    }

    selamVer("Ayşe"); // Merhaba, Ayşe!
    selamVer();      // Merhaba, Misafir!
Rest Parametreleri (...args) (ES6+)

Bir fonksiyona kaç argüman gönderileceğini önceden bilmediğimiz durumlarda rest parametreleri kullanırız. Gelen tüm ekstra argümanları bir dizi olarak toplar.


    function toplamHesapla(anaSayi, ...ekSayilar) {
        let toplam = anaSayi;
        for (let sayi of ekSayilar) {
            toplam += sayi;
        }
        return toplam;
    }

    console.log(toplamHesapla(10, 2, 3, 5)); // 20 (10 + 2 + 3 + 5)
    console.log(toplamHesapla(1, 2));      // 3 (1 + 2)
arguments Nesnesi (ES5 ve Öncesi)

ES6 öncesinde, fonksiyona gönderilen tüm argümanlara erişmek için arguments özel bir dizi benzeri nesne kullanılırdı.


    function eskiToplam() {
        let toplam = 0;
        for (let i = 0; i < arguments.length; i++) {
            toplam += arguments[i];
        }
        return toplam;
    }

    console.log(eskiToplam(1, 2, 3, 4)); // 10

Spread Operatörü (...) (ES6+)

Spread operatörü (...), bir diziyi veya yinelenebilir bir nesneyi tek tek elemanlarına "yaymak" için kullanılır. Fonksiyon çağrılarında argümanları bir diziden doğrudan geçirmek için çok kullanışlıdır.


    const sayilarDizisi = [10, 20, 30];

    function carpim(a, b, c) {
        return a * b * c;
    }

    console.log(carpim(...sayilarDizisi)); // 600 (10 * 20 * 30)

    // apply metodu ile eski kullanım (ES5)
    // console.log(carpim.apply(null, sayilarDizisi)); // 600

İleri Fonksiyon Konuları

Fonksiyonları Değişkenlere Atama ve Obje Metotları

Fonksiyonlar JavaScript'te birinci sınıf vatandaşlardır, yani onları değişkenlere atayabilir, başka fonksiyonlara argüman olarak gönderebilir veya fonksiyonlardan döndürebilirsiniz. Objelerin bir özelliği olarak tanımlanan fonksiyonlara metot denir.


    const user = {
        ad: "Ali",
        selamla: function() {
            console.log(`Merhaba, benim adım ${this.ad}.`);
        },
        // Ok fonksiyonu ile metot (this kullanımı farklıdır!)
        selamlaArrow: () => {
            console.log(`Merhaba, benim adım ${this.ad}.`); // this burada user objesini değil, global scope'u gösterir.
        }
    };

    user.selamla(); // Merhaba, benim adım Ali.
    user.selamlaArrow(); // Merhaba, benim adım undefined. (Tarayıcıda global this window objesi olur)
Fonksiyonların Fonksiyon Döndürmesi (Higher-Order Functions)

Bir fonksiyon başka bir fonksiyonu döndürebilir. Bu, özellikle karmaşık desenlerde ve daha esnek kod yazmada kullanılır.


    function carpanOlusturucu(carpan) {
        return function(sayi) {
            return sayi * carpan;
        };
    }

    const ikiIleCarp = carpanOlusturucu(2);
    console.log(ikiIleCarp(5)); // 10

    const ucIleCarp = carpanOlusturucu(3);
    console.log(ucIleCarp(5)); // 15
Recursive (Özyinelemeli) Fonksiyonlar

Bir fonksiyonun kendi kendini çağırmasına özyineleme (recursion) denir. Genellikle faktöriyel hesaplama veya ağaç yapılarını gezme gibi durumlarda kullanılır. Sonsuz döngüye girmemesi için bir temel durum (base case) olması çok önemlidir.


    function faktoriyel(n) {
        // Temel durum: n 1 veya 0 ise, 1 döndür
        if (n === 0 || n === 1) {
            return 1;
        }
        // Özyinelemeli durum: n * (n-1)!
        return n * faktoriyel(n - 1);
    }

    console.log(faktoriyel(5)); // 120 (5 * 4 * 3 * 2 * 1)
Promise'ler (Asenkron Programlama) (ES6+)

JavaScript tek iş parçacıklı (single-threaded) bir dildir, yani bir anda tek bir işlem yapar. Ancak, ağ istekleri gibi zaman alan işlemler programın donmasına neden olabilir. Promise'ler, asenkron işlemleri daha okunabilir ve yönetilebilir bir şekilde ele almamızı sağlar. Bir işlem başarılı olduğunda (resolve) veya başarısız olduğunda (reject) bir değer döndürür.


    function veriGetir(url) {
        return new Promise((resolve, reject) => {
            // Gerçek bir ağ isteği yerine setTimeout kullanarak simüle ediyoruz
            setTimeout(() => {
                if (url === "https://api.example.com/data") {
                    resolve("Sunucudan gelen veri!"); // İşlem başarılı
                } else {
                    reject(new Error("Geçersiz URL veya veri bulunamadı.")); // İşlem başarısız
                }
            }, 1000); // 1 saniye sonra dönecek
        });
    }

    console.log("Veri çekiliyor...");
    veriGetir("https://api.example.com/data")
        .then(veri => {
            console.log("Başarılı:", veri);
            return veriGetir("https://api.example.com/another-data"); // Zincirleme işlem
        })
        .then(veri2 => {
            console.log("İkinci başarılı:", veri2);
        })
        .catch(hata => {
            console.error("Hata oluştu:", hata.message);
        })
        .finally(() => {
            console.log("Veri çekme işlemi tamamlandı.");
        });
    console.log("İstek gönderildi, sonuç bekleniyor...");

Promise'ler, callback hell (iç içe callback'ler) sorununu çözerek daha temiz asenkron kod yazmamızı sağlar.


Sonuç

JavaScript'teki fonksiyonlar, kodunuzu yapılandırmanın ve tekrar kullanılabilir hale getirmenin temelidir. Farklı tanımlama yöntemleri, parametre yönetimi ve özellikle asenkron programlamada Promise'lerin kullanımı, modern JavaScript geliştirmenin olmazsa olmazlarıdır. Fonksiyonları ne kadar iyi anlarsanız, o kadar güçlü ve esnek uygulamalar geliştirebilirsiniz.

Bu konularda pratik yapmaya devam edin, farklı fonksiyon türlerini deneyin ve kendi projelerinizde cesurca uygulayın!

Webkolog'u takipte kalın!

Hepinize bol kodlu ve başarılı projeler dilerim!

0 yorum:

Yorum Gönder