14 Mayıs 2019 Salı

Modern JavaScript(ES6+) Eğitiminden Notlar

     S.a. Arkadaşlar,
     Son zamanlarda iyice yükselişe geçen js tarafına bir el atmak istiyordum. En son, öğrenmeyi isteme sürecinden öğrenme sürecine nihayet geçebilmiştim, ama o zamanlar bile bu öğrendiklerimle ilgili notlar alıp blog haline getirmeyi düşünüyordum. Tabi tüm bunlar dağınık bir şekilde duruyordu. Bugün onları derleyip size bu süreçte kendime aldığım notları sunmak istiyorum.

     Öncelikle let, const ve var kavramlarına bakalım. var ta eskilerden gelen hepimizin bildiği kavram, local global mantığı bulunmamaktır ve bu da farklı sıkıntılara sebebiyet verebiliyordu. let ve const ile bunun önüne geçildi. Aralarındaki temel fark ise const sonradan değişmeyecek değişkenlere verilmelidir. Burada dikkat edilecek bir konu ise aşağıdaki gibidir:

const array= [1,2,3];
array.push(5); 

Yukarıdaki kod parçası const olmasına rağmen hata vermez, bunun sebebi referans bazlı olmasıdır, fakat aşağıdaki kod hata verecektir. Bunun sebebi ise değer tipli olmasıdır.

const b= 3;
b = 5;

  Şimdi ise IIFE (Immediately-invoked Function Expressions) kavramına bakalım. Bunu Türkçe'ye anında çalışan fonksiyon ifadeleri olarak değiştirebiliriz. Bu yapıyı anlatmadan önce normal fonksiyon tanımı yapalım ve daha sonra aradaki farkı inceleyelim

let warning = function(message) {
 alert(message);  
};
var message="Hello World";
warning(message);

   Yukarıda tanımladığımız fonksiyonu birden fazla kez çağırabiliriz. Ama aşağıda tanımlayacağımız ve anında çalışacak olan metodu sadece bir kez çalıştırabiliriz.

(function(message) {
     alert(message)
})("Hello World");

    Scope kavramına geçelim. Burada global, function ve block tarzında 3 adet kapsama alanı vardır. Bunları kısaca açıklayacak olursak global her yerden çağrılabilen yapılardır. Function dediğimiz ise belirtilen fonksiyonda kullanılabilir. O fonksiyon dışında kullandığımızda hata verecektir. Block ise aslında fonksiyon ile aynı mantıkta olup belirli bloklar arasında sadece kullanılabilir.

    Arrow Function kod yazmayı oldukça kolaylaştıran bir yapıdır. Burada bir örnek vererek ne demek istediğimizi daha iyi açıklayacağız. Aşağıdaki kodda bir fonksiyon tanımlıyoruz. Bu fonksiyon verilen rakamın küpünü alıyor. Aşağıdaki kod da aynı işi yapmaktadır, ama daha basit ve sade bir şekilde.

//normal tanımlama
let cube = function cube(x){
   return x * x * x ;
}
cube(3);
//arrow function
const cube = x => x * x * x ;
cube(3);

      Destructuring assignment yine kod yazmayı çok pratikleştiren bir özelliktir. Hem dizilerle hem objelerle kullanılabiliyor. Dizi ve objeyi toplu bir şekilde değişkenlere atmamızı sağlıyor.

let a, b, rest;
[a, b] = [10, 20];
{ a, b } = { a: 10, b: 20 }

     İki yapıda da a = 10 ve b = 20 oluyor. Normal koşullarda bunu yapabilmek için dizi veya obje atamasını tek tek yapmak gerekirdi, fakat bu özellik ile bu oldukça kolaylaştı.

     Spread kod yazmamızı pratikleştiren başka bir yöntem. Bunun kullanımına bakacak olursa;

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];
console.log(sum(...numbers));
var arr;
[a, b, ...arr] = [10, 20, 30, 40, 50];

   1.örnekte ...numbers dizisi x , y ve z değerlerine atanarak çıktı 6 olacaktır. 2.örnekte ise a = 10, b = 20 rest ise dizi olup 30, 40, 50 değerlerinden oluşacaktır.

    for in yapısı hem obje hem dizi ile kullanılır. Örnekte 1 ve 2.satırların ikisi ile ayrı ayrı çalışacaktır. Buradaki yapıyı foreach ile karıştırmamanız önemli. Çünkü burada objeye erişim obj[item] şeklinde olmaktadır. Aşağıdaki örnekte daha iyi anlayacağınızı umut ediyorum.

//let object1 = [1,2,3]; 
let object1 = {a: 1, b: 2, c: 3};

for (var property1 in object1) {
  console.log(object1[property1]);
}

   for of yapısı sadece dizi ile çalışır. Obje ile çalışmaz. Buradaki yapı foreach yapısına benzemektedir, fakat burada dikkat edilmesi gereken şey de obje üzerinde çalışamayacağımız için property1.variable1 diye erişmek istediğimizde hata ile karşılaşacağız.

//let iterable = {a: 1, b: 2, c: 3};
let iterable = [10, 20, 30];
for (let value of iterable) {
  console.log(value);
}

    1.satırı yorum satırından çıkarıp kodu derlemeye çalıştırırsak "iterable is not iterable" gibi bir hata ile karşılayacağız. Bunu da göstermiş olduk.

    Blocking beni en çok heyecanlandıran kısım. Bunun sebebi belki de bir backend developer olarak yetişmem de olabilir. Çünkü js bildiğiniz üzere non blocking bir dil. Yani java veya c# gibi dillerde olduğu gibi bir iş yaparken diğer işleri bekletmez. Bu aslında büyük bir avantaj, fakat bazı işlemleri yaparken de bunun beklemesi lazım. Örneğin, veri tabanından kullanıcı tablosuna gitmemiz gerekiyor, oradan adres tablosuna, belki de oradan da başka bir tabloya. Burada işlemleri sıra ile yapmadığında hata oluşacaktır. Çünkü adres tablosunda hangi kullanıcının adresini alacak. Bu gibi işlemleri bloklamak için 3 yapı bulunmaktadır. Bunlar eskiden yeniye: callback, promise, async await yapılarıdır.

//kod kaynağı
//call back
function printString(string, callback){
  setTimeout(
    () => {
      console.log(string)
      callback()
    }, 
    Math.floor(Math.random() * 100) + 1
  )
}

function printAll(){
  printString("A", () => {
    printString("B", () => {
      printString("C", () => {})
    })
  })
}
printAll()
//promise
function printString(string){
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
       console.log(string);
       resolve();
      }, 
     Math.floor(Math.random() * 100) + 1
    )
  })
}


function printAll(){
  printString("A")
  .then(() => printString("B"))
  .then(() => printString("C"))
}
printAll()
//async await
function printString(value){
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
       console.log(value);
       resolve();
      }, 
     Math.floor(Math.random() * 100) + 1
    )
  })
}


async function printAll(){
  await printString("A")
  await printString("B")
  await printString("C")
}
printAll()

  1. kod bloğunda callback yapısı mevcuttur. Bu aralarındaki en eskisi ve en hızlı yapıdır, fakat kod okunurluğunu düşürdüğü için tavsiye edilmiyor. İleride callback hell denilen yapının ortaya çıkma ihtimali yüksektir.

   2.kod bloğu ise promise yapısı olup es6 ile gelmiştir. Burada kod okunurluğu daha düzgün olmasına rağmen hala bir parça kod okunurluğunu düşürmektedir, fakat hızı callback yapısından bir tık azdır. Hata yakalama için de catch yapısı kullanılabilir.

   3.kod blok ise es7 ile gelen async await yapısıdır. Blocking olan dillerde yaygın olan bir yapıdır. En düzgün kod görünümü burada olmakla birlikte aralarında en yavaş olan yapı da budur.

    Tabi bunların seçimi projeye göre değişir. Bunların üzerine yazılmış oldukça fazla yazı bulunmaktadır. Bunlardan birine buradan erişebilirsiniz. Ayrıca bu yazıya da göz atmanızda fayda olacaktır. Tüm bunlarla birlikte js'in backend konusunda çok avantajlı olmadığıyla ilgili şu yazıya göz atmanızı tavsiye ederim.

     fetch api , $ajax'ın yerine kullanılan yapıdır, fakat tüm tarayıcılarda desteklenmemesi şuan için oluşan bir problemdir. Bunu da çözmek için fetch polyfill kullanabilirsiniz.

    Babel çoğu tarayıcının, kısmi özelliklerini anlamadıkları es6 ve es7 kodlarını es5(2009'da yayımlandı, çoğu tarayıcı tarafından tüm özellikleri desteklenmektedir.) çevirmesini sağlar. Kendi sitesinden inceleyebilirsiniz.

   webpack kullanmış olduğumuz paketleri tek bir .js çıktısı olarak bize döner. Bu da bize sayfanın ön yüklenme süresini oldukça kısaltacaktır. Bu yapı ayrıca paket yönetimini de merkezileştirerek kolaylaştırmaktadır. Son iki başlıkla ilgili ayrıntılı inceleme yapmak isterseniz buraya uğrayabilirsiniz.

    Kendime aldığım notları elimden geldiğince kısa ve öz bir şekilde anlatmaya çalıştım. Güzel ve faydalı bir yazı olması dileğiyle.

Hiç yorum yok:

Yorum Gönder