Herkese merhaba!

Bu yazımda EcmaScript’in Javascript’e getirdiği yeniliklerden, ve ben bu yenilikleri projelerimde nasıl kullanıyorum ondan bahsedeceğim.

Son zamanlarda yoğun bir şekilde React projeleri yazıyorum. Bunların bir kısmı webpack ile, bir kısmı browserify ile paketlenen projeler, aralarındaki ortak ve keyifli nokta ise babel sayesinde javascript’in en son eklenen, daha tarayıcıların bile desteklemediği özelliklerini kullanabiliyor olmak. Javascript, her sene iteratif çıkacak olan özellikler sayesinde, o sıkıcı diyebileceğimiz halinden, yazması en keyifli dillerden biri haline geldi. Önerilen özelliklere ve durumlarına TC39’un Github sayfasından bakabilirsiniz.

okuyucuya not: yazı boyunca var yerine let ve const kullanıyor olacağım. Bunlar da es6 ile gelen yeni değişken tanımı yaparken kullandığımız keywordler. var’dan farkları function değil block scope dahilinde olmaları, ayrıca const ile atanmış değişkenin başka bir yerde tekrar atanamıyor olması. let ile tekrar değer atama yapabilirsiniz. const ile tanımlanmış olan eğer obje ise property değerini veya dizi ise o indexteki değeri değiştirebilirsiniz, ama objenin veya dizinin yerine tekrar atama yapamazsınız.

1) Arrow functions

Tüm callback’ler artık şu yazımı güzel olan arrow function’a döndü.

    fetchData().then((res) => {
        return res.data;
    });

Ne kadar güzel gözüküyor değil mi 😍 ortadaki ok gibi gözüken => sembolüne ‘fat arrow’ deniyor (coffeescript yazmış olanlar -> şeklinde bir arrow görmüşlerdir, alışması zor olabilir)

    const getId = (res) => {
        return res.id;
    });

Arrow function şeklinde yazılmış fonksiyonları da değişkenlere atayabiliyoruz. Aslında arrow function sadece 1 değişken alıyorsa method imzasında parantezlere gerek yok. Hiçbir değişken almıyorsa veya birden fazla alıyorsa gerek var.

    const getId = res => {
        return res.id;
    };

    const doSomething = () => { 
        something();
    }

    const doSomething2 = (a, b) => { 
        something();
    }

Hatta, eğer sadece bir return ifadesi içeriyorsa, yani ayrıca bir işlem yapmıyorsa (pure function ise) süslü parantezleri ve return ifadesini de kaldırabilir, şu şekilde yazabiliriz:

    const getId = (res) =>  res.id;

Arrow function’ın gelmesinin tek derdi syntax’ı güzelleştirmek değil, this kelimesini mantıklı hale getirmek.

Çoğunuz şöyle bir kod parçacığı görmüşsünüzdür:

    function MyConstructor(data, transport) {
        this.data = data;
        var self = this;
        //bir diğer hali: 
        var _this = this;
        transport.on('data', function() {
            alert(self.data);
        });
    }

Javascript dilinde her fonksiyon birer obje olduğundan, hepsinin içerisindeki this kendi context’ine ait. O yüzden callback içerisinde kullanılacak this artık MyConstructor’u göstermediğinden onu değişkene atıp o şekilde kullanıyorduk. Ancak arrow function’larda bu problem çözülmüş durumda. Bir arrow function’ın içinde çağırdığınız this parent objeye referans veriyor.

    function MyConstructor(data, transport) {
        this.data = data;
        transport.on('data', () => {
            alert(this.data);
        });
    }

2) Property destructing

En çok keyif alarak kullandığım yenilik. Kod yazmayı çok verimli hale getirdiğini düşünüyorum.

    let obj = {
        id: 1,
        type: 2,
        name: 'Test'
    }
    const { id, type } = obj;
    getById(id);

Yukarıdaki kodda obje içerisinden sadece kullanacağım özellikleri alıp ayrı birer değişkene atamış oldum. Bu şekilde hem objenin bir değişkeni için tamamına dokunmamış oldum, hem de keyif veren ve daha okunabilir bir kod yazdım. Sadece verimlilik değil, okunabilirlik ve yazdığı kodun geliştiriciye verdiği keyif açısından düşündüğümüzde de değeri yüksek.

Bir diğer kullanımı, methodlara geçilen objelerden gerekli özellikleri alırken kullanabilirsiniz:

    let obj = {
        id: 1,
        type: 2,
        name: 'Test'
    }

    const getById = ({ id }) => {
        return doSthWithId(id);
    }

    getById(obj);

getById methodunun objenin tamamını bilmesine gerek yok. Ama yarın o method, name’in değerine de ihtiyaç duyabilir. O zaman yalnızca bir hamle ile erişebilir hale getiriyoruz:

    const getById = ({ id, name }) => {
        return doSthWithId(id);
    }

id’nin yanına name’i ekleyerek bu ihtiyacı karşılamış olduk. 😎

3) Template literals

’+’ ile stringleri birleştirmek artık tarihe geçti. `` işaretleri arasında yazdığınız string değerlerin içerisinde ${} ile değer dönen herhangi bir javascript kodu yazabiliyorsunuz.

not: ` işaretini daha önce yazdığım dillerde de çok kullanmadığımdan nasıl yapıldığını bilmiyordum. Benim gibiler için Mac’te türkçe klavyede alt+noktalı virgül ile yapıyorum.

    //eskiden: 
    var isim = "Durul";
    console.log("Merhaba" + isim);

    //Template literals ile
    const name = "Durul";
    console.log(`Merhaba ${name}`);
    //Merhaba Durul

    const obj = {
        name: "Okuyucu"
    };
    console.log(`Merhaba ${obj.name}`);
    //Merhaba Okuyucu

    const getName = () => { return "Test" }
    console.log(`Merhaba ${getName()}`);
    //Merhaba Test
 

Kullanımı basit, anlaşılır ve keyif verici 👌🏻. Literal string ayrıca yeni satırları olduğu gibi çıkarır, string içerisinde \n girmenize gerek kalmaz:

    const name = "Okuyucu";
    console.log(`Merhaba ${name},
    Bugün
    Kendini
    Nasıl
    Hissediyorsun?`);

    /*
    Merhaba Okuyucu,
    Bugün
    Kendini
    Nasıl
    Hissediyorsun?
    */
 

Ayrıca ` ve ${} karakterleri literal içerisinde özeldir, kullanabilmek için \ escape etmek gerekir.

    console.log(`Template literal \` işaretleri içine \${} işaretleri kullanılarak yazılır.`);

    //Template literal ` işaretleri içine ${} işaretleri kullanılarak yazılır.
 
    // ${} işaretinin tek başına escape edilmesi yeterlidir, \${} şeklinde.

Template literal’in bir de Tagged hali var. Literal string’inin oluşmasından önce bir tag function denilen bir fonksiyondan geçiyor. Tam olarak şöyle:

    function selamla() {
        console.log(arguments);
    }
    let name = "Okuyucu";
    selamla`Merhaba ${name}`;
    // ["Merhaba", ""], "Okuyucu"

Aslında selamla() methodu üzerinden literal’i çalıştırıyoruz. Bunu da şurdan anlayabiliriz:

    function selamla(str, nameArg) {
        return `selamlar! hoşgeldin ${nameArg}`;
    }

    let name = "Okuyucu";
    selamla`Merhaba ${name}`;
    //selamlar! hoşgeldin Okuyucu

Bu sayede template literal’inin nasıl oluşacağına karar veriyoruz. Bu method içinde işlem de yapabilirsiniz.

4) Obje ve dizi rest/spread operatörleri

En garip bölüme geldik 😂. İlk bakışta kafa karıştırıcı, ama öğrendikten sonra çok kolay ve doğru kullanıldığında verimli kod yazmayı sağlayan bir yenilik, hem objelerde, hem de dizilerde rest ve spread operatörleri kullanımı.

    //Rest Operator
    const obj = {
        a: 1,
        b: 2,
        c: 3,
        d: 4,
        e: 5
    }

    const { a, b, ...z } = obj;
    console.log(a, b, z);
    // 1, 2, { c: 3, d: 4, e: 5}

    //Spread Operator

    const obj2 = { a, ...z }
    console.log(obj2);
    // { a: 1, c: 3, d: 4, e: 5 }

Biraz karışık gözükse de, aslında kelime karşılığı tam olarak ne yaptığını anlatıyor.

Rest: Bana a, b ve “diğerlerini” ver

Spread: a’yı al, gerisini bunlardan dağıt 😂

Rest kısmında a, b, c, d ve e propertyleri olan bir objemiz var. Property destructring yaparak a ve b’yi alıyorum, ancak geri kalanına da ihtiyacım var ve onları bir arada almak istiyorum. ‘Rest’, yani Geri Kalanı ile a ve b dışındakileri z adında yeni bir objeye atıyorum.

Spread kısmında ise yeni bir obje tanımı yapıyorum, objeye a’yı ekliyorum ve z objesinin tüm propertylerini de bu yeni objeye dağıtıyorum.

Rest operatörünü ayrıca methodlarda olan property destructing örneklerine de verebiliriz.

    const getById = ({ id, name, ...rest }) => {
        return doSthWithId(id);
    }

Bu şekilde getById fonksiyonu id ve name’e değişken isminden, geçilen objenin geri kalanına da rest adında yeni bir obje üzerinden erişebilir oldu.

React, Component yazarken state’i değiştirmemenizi ve o state üzerinden yeni bir obje dönmenizi prensip olarak belirtir. O yüzden lokal state değişikliklerinde veya eğer Redux kullanıyorsanız reducer methodlarda bolca görebilirsiniz.

    this.setState({
        ...this.state,
        loading: false
    })

Spread operatörü kullanılarak obje yaratıldığında, eğer o property önce tanımlanmışsa onun değeri değişir.

    const obj = { a: 1, b: 2, c: 3 }

    const obj1 = { ...obj, b: 3 } 
    console.log(obj1);
    //{ a: 1, b: 3, c: 3 }

    const obj2 = { b: 3, ...obj } 
    console.log(obj2);
    //{ b: 2, a: 1, c: 3 }

Gelelim dizi spread operatörlerine. Dizilerdeki en büyük artısı birden fazla diziyi istediğiniz noktadan birbirine bağlamak.

    const arr1 = [1, 2];
    const arr2 = [3, 4, ...arr1, 5, 6];
    console.log(arr2);
    //3, 4, 1, 2, 5, 6

Normalde bunu yapmanın bir çok yolu var, ancak bu haliyle kod okunabilirliği açısından maksimum verim sağlıyor. Yine React state yönetimi kısmında, veya redux reducer’ları içerisinde dizilerde değişiklik yapılacağı zaman eski diziye dokunulmaması ve yeni bir dizi dönmesi istendiğinde spread operatör çok faydalı olabilir. Egghead’de olan Redux örneğinde şu şekilde görülebilir:

    const addCounter = (list) => {
        return [...list, 0];
    }
    const removeCounter = (list, index) => {
        return [
            ...list.slice(0, index),
            ...list.slice(index + 1)
        ];
    }
    const incrementCounter = (list, index) => {
        return [
            ...list.slice(0, index),
            list[index] + 1,
            ...list.slice(index + 1)
        ];
    }

Redux ile uğraşırken bol bol spread kullanıyor olacaksınız. 😅

Spread operatörünü bir de diziyi kopyalarken kullanabiliriz:

    const arr1 = [1, 2];
    const arr2 = [...arr1];
    arr2.push(3)
    console.log(arr2);
    //1, 2, 3

5) Property-value shorthand notation

Bir objeye property atarken eğer atayacağınız değişkenin ismi ile property ismi aynı ise tekrar kendisini yazmanıza gerek kalmıyor.

    const name = "Okuyucu"
    const obj = {
        id: 1,
        name
    }

Kod okunabilirliği ve temiz kod yazımı konusunda faydalı.

Son olarak;

Uzun süredir Javascript yazan biri olarak önyüz camiasında olan gelişmeler hali hazırda beni fazlasıyla heyecanlandırırken, dilin kendisinin güzel yönde değişimi hepsinden önce geliyor ve mutlu ediyor. Şahsen, böyle devam etmesi en büyük isteğim. Sizin en çok kullandığınız yenilik hangisi? Yorumlara yazabilirsiniz!

Keyifli kodlamalar!