ES6 / ES7 ile Javascript e gelen yenilikler

This post is part of the series Template literals : `${} ${}`

İster Angular ile uygulama geliştirelim, ister başka bir framework kullanalım  bugünlerde Javascript in en son standart sürümü olan “ECMAScript 6” yada kısaca ES6 ile gelen yenilikleri öğrenmek ve bunları uygulamalarımzda kullanmak  önemli. Bazen kafa karışıklıklığı olduğu için kısaca tekrar edecek olursak ,

Typescript, javascript üzerine kurulmuş ve  bilinen özelliklerine bazı eklemeler(geliştirme süreci için) yapan bir üst Javascript versiyonu diyebiliriz. Yani, TypeScript içinde ki bir çok kavram ve araç aslında Javascript in dahili parçaları. Typescript ise iki şey yapmakta, yazdığımız kodları dilersek daha eski sürüm Javascript versiyonlarına çevirme ve geliştirme sürecinde Javascript dil yapısına bazı eklemeler yapmakta.

TypeScript = %70 Javascript + %20 Typescript eklemeleri + %10 tooling ( kod tamamlama,  dönüşüm vb. ) şeklinde bir tanımlama yapabiliriz. Bu sebebten, ister angular özelinde isterseniz diğer frameworklerle kullanımda, Javascript i daha iyi kavramak çok önemli .

Javascript , ES6 ile bir çok yenileğe kavuştu, Class anahtar kelimesi , değişkenlerimizi tanımlamak için yeni yöntemler , generators, arrow functions … bunlardan bir kaçı. Bu yazıda Javascript in bu yeni sürüm ile kazandığı yeni özelliklere bakmaya çalıaşcağız.

Değişkenler ve Değişken Etki Alanları

let:

ES6 ile yeni gelen anahtar kelimeleden biri olan “let” javascriptin müzmin sorunlarından birini(hoisting) çözmek için bir alternatif sunmakta. Temel işlemi, tıpkı “var” gibi değişken tanımlama olsada, artık “block level” – tanımladığını blok içinde etki alanına sahip değişkenler tanımlamamıza imkan vermekte.

function ogrenciKursFiyatı(ogrenci) {
 if (ogrenci.aktif) { 
  let sonFiyat = ogrenci.kursFiyat - 100;
  return sonFiyat
 } 
// sonFiyat if bloğu dışında erişelebilir değil! 
   console.log(sonFiyat) // Error!!
   return ogrenci.fiyat;
 }

Yukaridaki örneğe baktığımız da, sonFiyat isimli değişken let ile tanımlandığı için, (sadece tanımlandığı blok içinde erişilebilir olacaltır.) if() {…} bloğu dışında erişilebilir değildir.  Eğer let yerine eski usul var ile bir tanımlama yapılsaydı , fonksiyonun içinde her yerde erişilebilir olacaktı. İşte let ile bu önemli sorun çözülmüş oldu. Artık Javascript içinde sadece “block level”  değişken tanımlama imkanına kavuştuk.  

Constant / Sabit Tanımlama – const

ES6 ile artık, javascript içinde sabit değişkenler tanımlayabileceğiz. Etki alanı olarak let  ile aynı yapıya sahip olduğunu (tanımlandıkları blok seviyesinde erişilebilirler) hatırlatalım.

const PI_SAYISI= 3.14; // PI_SAYISI değişkenine artık yeni bir değer atayamayız!
PI_SAYISI= 7; // SyntaxError

const ile ilgili önemli bir nokta var,  eğer const ile bir object tanımlaması yaptıysanız yada Array , bu iki veri yapısının doğası gereği, referans değişikliği yapmadığınız sürece, nesneyi yada diziyi modifiye edebilirsiniz.

const ARABA= {};
ARABA.renk = 'mavi'; // ARABA isimli değişkeni modifiye edebilmekteyim

fakat , referansını değiştirmeye çalışırsam hata alacağım

ARABA= {renk: 'mavi'}; // SyntaxError
// ARABA nesnesini modifiye etmiyorum, yeniden bir değer atamaktayım!
//buyüzden hata alacağım.

aynı kural diziler içinde geçerli

const ARABALAR= [];
ARABALAR.push({ renk:"mavi" }); // geçerli kullanım
ARABALAR = []; // SyntaxError
ARABALAR = 5 // SyntaxError

Objects – Nesnelerle ilgili yenilikler.

1- Object Creation : Yeni Nesne Oluşturma

ES6 e kadar bir Object/nesne oluşturmak istediğimizde, hem anahtar hem değer i beraber kullanıyorduk. Es6 ile ise eğer, anahtar ve değer aynı ismi taşıyorsa biraz daha kısa bir tanımla kullanabilmekteyiz.

Eski Usul: 

function yeniNesne() {
  var isim = 'Ali';
  var soyad = 'Veli';
  return { isim: isim, soyad: soyad };
}

Yeni şekli:

function yeniNesne() {
  let isim = 'Ali';
  let soyad = 'Veli';
  return { isim, soyad }; // hem anahtar hemd edeğer aynı isimde olduğu için
  //isim:isim gibi. 
}

2- Object Destructuring : Bir javascript nesnesinden yada dizisinden, değişkenleri almak

Eski Usul: 

var httpRequest = { method:"GET", url:"/api/products" };
// yukarıdaki gibi bir nesneden değişkenleri almak için
var method= httpRequest.method;
var url = httpRequest.url;

Yeni Şekli:

const httpOptions = { method:"GET", url:"/api/products" };
// later
const { method , url} = httpRequest;

Böylece, daha kısa bir yazım şekli ile, nesnemizden ilgili anahtarları kullanarak yeni değişkenler oluşturmuş olduk. Artık, method  ve  url isimli iki değişkenimiz oldu.

const { method , url} = httpRequest;
console.log("web isteği için url : ", url)

Default parameters and values – Varsayılan değer ve parametre tanımlama.

ES6 ile gelen en güzel özelliklerden biride, artık ister fonksiyonlarımız için , isterse nesnelerimizden değer alırkan olsun, varsayılan değerler tanımlayabilmemiz. İlk olarak, bir önceki başlık da konuştuğumuz “Object Destructuring ”  örneğimize bakalım. Eğer “method” değeri sağlanmamış ise varsayılan bir değeri kullanmak istediğimizi var sayalım.

const { method = "POST" , url} = httpRequest; // eğer httpRequest nesnesi bir "method" değeri taşımıyorsa,
//method değişkenimiz varsayılan değeri alacak "POST".

Aynı şekilde , fonksiyonlarımızdaki parametreler içinde varsayılan değerler atayabileceğiz.

Eski usul ile bakacak olursa,

function vergiHesapla(fiyat, oran) {
  oran = oran || 18; // eğer oran parametresi her hangi bir değer taşımıyorsa
  return fiyat * (oran/100)
}

yeni şekli ile

function vergiHesapla(fiyat, oran = 18) {
  return fiyat * (oran/100)
}

artık, oran isimli parametre eğer bir değer atanamaz ise 18 değerini taşıyacaktır. Varsayılan değer olarak başka bir fonksiyonda kullanabiliriz:

function vergiHesapla(fiyat, oran = vergiOranGetir() , adet=1 ) {
  return (adet * fiyat) * (oran/100)
}

Javascript doğası gereği, bir fonksiyona geçilen parametrelerin sayısı ile ilgilenmez, yukarıdaki fonksiyonu aşağıdaki gibi çağırırsak bir sorun yaşarız örneğin;

let fiyat = 100,
let adet = 3 
let toplam = vergiHesapla(fiyat,adet)

yukarıdaki gibi bir kullanımda, fiyat ve adet bilgisini fonksiyona iletirken , vergi oranı için her hangi bir değer kullanmıyoruz. varsayımsal olarak , varsayılan vergi oranımız olan “18”  in kullanılacağını düşünebiliriz ama öyle olmayacaktır. Javascript vergiHesapla(fiyat,adet) fonksiyonuna iki parametre gönderdiğimiz için, ilk parametreyi , “fiyat”  değişkenine, ikincisini “oran” değişkenine atayacaktır.

fonksiyonumuz çalışırken şu değerleri aldığını varsayacaktır:

fiyat = 100 , oran = 3 (normalde adet) ve 3. parametre olan adet parametresinin gönderilmediğini düşünüp, varsayılan değer olan “1” i kullanacaktır. Bu durumun üstesinden gelebilmek için

1- Parametrelerin sırasını doğru ayarlamak ( vergiHesapla(fiyat,null, adet)  gibi) yada,

2- Parametreyi bir nesne olarak yeniden yapılandırmak gerekecekdir, örneğin :

function vergiHesapla({fiyat, oran = 18 , adet=1 }) {
  return (adet * fiyat) * (oran/100)
}

gibi, bu şekilde parametreleri bir nesne olarak aldığımızda , isimlendirilmiş parametre etkisi oluşturabiliriz böylece istediğimiz sayıda parametreyi istediğimiz sırada kullanabiliriz. Çünkü artık bir nesne/Object üzerinden değer alacağımız için, parametrenin sırası değil ismi kullanılacaktır.

let fiyat = 100,
let adet = 3 
let toplam = vergiHesapla({fiyat,adet})

artık işlemimiz doğru bir şekilde gerçekleşecektir. Fonksiyonumuz bir nesne aldığı için parametreleri anahtar değerlere (isimlere) göre eşleyecekdir.

 Classes

ES6 ile Javascript e gelen yeniliklerden biride “class” anahter kelimesi. Artık Javascript içinde sınıf tanımlamalarında aşağıdaki gibi yeni bir söz dizimi kullanabileceğiz.

class Ogrenci{

//Yapıcı Metodumuz
constructor(isim,soyad) { 
 this.isim = isim;
 this.soyad= soyad
}
//toSting metodumuzu Override ettik
toString() {
    return `${this.isim} ${this.soyad}`;
  }
}
const ogrenci= new Ogrenci("Ali", "Veli"); // yeni ogrenci sınıfı örneği
console.log(ogrenci.toString()); // Ali Veli

En temel haliyle sınıfımıza bakacak olursak, tıpkı C#, Java gibi OO diller de olduğu  gibi, class keyword ü ile sınıf tanımlamamıza başladık.

class Ogrenci {
...
}

Bir diğer özellikde, constructor() metodumuz,

constructor(isim,soyad) { 
  this.isim = isim;
  this.soyad= soyad
}

öğrenci nesnemizi new keyword ü ile oluşturuğumuzda ilk önce çağrılacak metodumuz(constructor). Böylece sınıfımız için gerekli verileri bi örneğin oluşturulma sürecinde temin edebilmekteyiz.

constructor içinde,

this.isim = isim;

şeklinde ki kullanımız ise bir çok OO dildeki kullanımla aynı diyebiliriz, artık, ogrenci sınıfımızın , “public member” / dışarıdan erişelebilir iki  üyesi oldu. Böylece sınıfımızı oluşturduktan sonra aşağıdaki gibi erişebiliriz.

const ogrenci= new Ogrenci("Ali", "Veli"); // yeni ogrenci sınıfı örneği
console.log(ogrenci.isim); // Ali 
ogrenci.isim = "Ayşe"
console.log(ogrenci.toString()) // Ayşe Veli

Javscript içinde tanımladığımız sınıflarda “static” üyelerde tanımlayabiliriz

class Araba{ 
  static fiyat() { 
      return 100000; 
   }
}

static olarak tanımladığımız metodları, sınıfın bir örneğini oluştumadan kullanabiliriz.

Araba.fiyat() // 100000

new ile oluşturacağımız sınıf örnekleri üzerinde, static üyelerimize erişemeyeceğimizi unutmayın. Aşağıdaki gibi bir kullanım hataya sebep olacaktır.

let araba = new Araba()
araba.fiyat() // Error!

C#, Java gibi dillerden alışık olduğumuz, “getters and setters” kullanımıda benzer bir şekilde Javascript sınıflarımızdada mevcut

class Araba {
    get renk() {
        console.log('Araba Rengi');
        return this._renk;
    }

    set renk(yeniRenk) {
        console.log(`Araba renk degiştir : ${yeniRenk}`);
        this._renk = yeniRenk;
    }
}
const araba = new Araba();
araba.renk = 'Mavi';
// Araba renk degiştir : Mavi
console.log(araba.renk);
// Araba Rengi
// 'Mavi'

Yukarıdaki örnekte , “alt tire /  underscore ” ile başlayan bir tanımlama yapmadığımız halde,  “this._renk” şeklinde ilgili alana ulaşabildğimize dikkat edin. Getter ve setter metodları bizim için bu “private değişken i” otomatik olarak oluşturacaktır.

Javascript, ES6 ile birlikte artık sınıflarımızın inheritance/miras alma yeteneği içinde yeni bir keyword a sahip “extends“. Java dan hatırlayacağınız bu keyword ile sınıflarımızın bir üst sınıfı miras almasına imkan vermiş oluyoruz.

class Tasit {
    constructor(hiz) {
        this.hiz = hiz;
    }
}
class Araba extends Tasit {
    constructor(hiz, renk) {
        super(hiz);
        this.renk = renk;
    }
}
const araba = new Araba(20, 'mavi');
console.log(araba.hiz); // 20

Araba sınıfımız yukarıdaki örnekte , Tasit isimli diğer sınıfı miras almakta. taşıt sınıfımızdaki constructor a ulaşmak içinde tıpkı javada olduğu gibi super (yada C# daki base) metodumuzu kullanabilmekteyiz.

Es6 ile Javascript ile gelen classsınıf yapımız, Java yada C# daki gibi gelişmiş ve Gerçek bir “sınıf tabanlı model” değil. Ama Javascript içinde bir çok ihtiyaca cevap verecek seviyede. Java yada C# gibi dillerdeki access modifiers (public, private vs) yada interface kavramı gibi bir çok yetenek Javascript sınıfımlarımız için kullanılabilir değil.

Bunun nedeni, zaten Javascript içinde başka bir model olan “javascript prototype inheritance” prototip temelli miras alma modelinin mevcut bulunması. Bu model çok esnek ve yetenekli olsada kullanımı “class” yapısı kadar kolay ve anlaşılır değil, ayrıca diğer dillerden geçen programcılar içn öğrenilmesi genelde zor. Bu yüzden, ES6 ile Javascript de sade ama iş görür yeni bir alternatif olarak “class” yapısı dahil edilmiş.

‘fat arrow’ operator (). / Yeni fonksiyon yazim sentaksi

fat arrow diye isimendirilen bu yeni yontemin bize sagladigi iki onemli kolaylik var ;

  1. Daha sade ve kısa bir fonksiyon tanımlama yöntemi
  2.  this keyword ü için scope güncellemesi.

İlk olarak 1.maddeye bakalım , Javascript ile her zaman alışık olduğumuz şekilde bir fonksiyon tanımlayalım ve kullanalım;

let vergiHesapla = function (fiyat, vergiOrani) {
    return fiyat * (vergiOrani/100)
}

let vergiliFiyat = vergiHesapla(100, 18)

şimdi aynı fonksiyonu, ES6 ile yani “fat arrow” ile tekrar yazalım;

let vergiHEsapla = (fiyat, vergiOrani) => {
    return fiyat * (vergiOrani/100)
}

yukarıdaki yazım şeklimize baktığımızda, ilk olarak “function” keyword ünü artık kullanmadığımızı onun yerine parametrelerden sonra => (fat arrow) kullandığımızı görüyoruz. Bu haliyle eski halinden çok da bir farkı yok diyebiliriz. Ama dahada kısa hale getirebiliriz yazım şeklini

Örneğin aşağıdaki gibi yazabiliriz mesela

let vergiHEsapla = (fiyat, vergiOrani) => fiyat * (vergiOrani/100)

fonksiyon gövdemizide kaldırdık , ayrıca fonkiyonumuz tek bir satırla değer döndürdüğü için return nü de artık kullanmayabiliriz.  eğer fonksiyonumuz tek bir parametetre alıyorsa, ( ) parantezleride kullanmayabiliriz.

let kullanciBul= isim => db.find(isim)

yukarıdaki örnek aşağıdaki ile aynı

let kullanıcıBul = (isim) => db.find(isim)

parantez kullanımı, tek bir parametre olduğunda isteğe bağlı olsada ben her zaman kullanmaktan yanayım. kodların bir fonksiyon çağrısı yaptığı daha kolay anlaşılıyor okuma kolaylığı açısıdnan parantezlerin kullanılması faydalı diyebiliriz.

Eğer herhangi bir parametre almıyorsa , ozaman ( ) kullanımı mecburi,örneğin

let kullanıcıBul = (isim) => db.find(isim)

fat arrow u , tabiki callback olarak da kullanabiliririz

db.users.find({id:5}, (err, user ) =>{
    console.log("user : ", user)
})

fat arrow ile gelen diğer bir yenilik de, this keywordünü artık doğru contex içinde (etki alanında) kullanabilmemiz. Aşağıdaki örneğe bakalım;

var enYuksekNot = {
    max: 0,
    find: function (notlar) {
        var self = this;
        // bir sonraki adimda, this in scope u degisecegi icin
        //self isminde bir degisken tanimladik
        notlar.forEach(
            function (not) {
                if (not > self.max) {
                    self.max = not;
                    //this.max => this artik enYuksekNot nesnesini degil
                    //icinde bulundugu fonksiyonu isaret etmekte
                    //o yuzden, self.max ile dogru referansa ihtiyacimiz oldu.
                }
            });
    }
};

enYuksekNot.find([20, 43, 64]);
console.log(enYuksekNot.max);

yukarıdaki örnekde, yorum satırlarında belirtmeye çalıştığım gibi this  ile doğru referansı kullanabilmek için , yeniden bir değişken tanımlamak zorunda kaldım. Diğer bir alternatif olarak, bind() metodu ile , doğru referansı bildirebilirdim;

notlar.forEach(
    function (not) {
        if (not > self.max) {
            this.max = not;
        }
    }).bind(this)

her iki kullanımda doğru olsada, this in referansını doğru takip edebilmek ve daha kolay anlaşılır kod yazabilmek için artık fat arrow kullanabilmekteyiz. Bu şekilde, this bizim için her zaman olması gerektiği gibi blok seviyesinde referans edilecek. örneğin aşağıdaki gibi bir yazım şeklimiz olacak:

notlar.forEach( (not) => {
    if (not > this.max) {
        this.max = not;
    }
});

Sets and Maps – 2 Yeni veri yapımız

Javascript artık iki yeni Collection türüne sahip, Set ve Map .

Set ile unique/tekil değerleri tutabileceğiz

const ogrenci = { id: 1, name: 'Ali' };
const ogrenciler = new Set(); // set olustur
ogrenciler.add(ogrenci); // ogrenciyi ekle
console.log(ogrenciler.has(ogrenci)); // true
console.log(ogrenciler.size); // 1
ogrenciler.add(ogrenci); // ayni ogrenciyi tekrar eklemeye calisalim. 
// Hata almayacagiz ama tekil bir liste tutuldugu icin
//ekleme yapilmayacak
console.log(ogrenciler.size); // hala 1
ogrenciler.delete(ogrenciler); // ogrenciyi sil

Map ise , tıpkı klasik Javasript nesnelerimiz gibi, key/value – anahtar/değer ikililerimizi tutabileceğimiz bir yapı.

const ogrenci = { id: 1, name: 'Ali' };
const ogrenciler = new Map(); // Map olustur
ogrenciler.set(ogrenci.id, ogrenci); // ogrenci ekle, key :id, değer : isim
console.log(ogrenciler.has(ogrenci.id)); // true
console.log(ogrenciler.size); // 1
ogrenciler.delete(ogrenci.id); // öğrenci sil

Set ve Map den önce , Javascript nesnelerini bu tür ihtiyaçlarımız için kullanmaktaydık. Halada kullanmak mümkün fakat, set ve map in Collection olarak daha özelleşmiş olduğunu ve bir çok işlemi klasik Object = {key:value} den daha kolay yapabildiğimizi hatırlatmakta fayda var. Örneğin iki tür içinde .size çağrısı ile kolayca eleman sayısını öğrenebilmekteyiz, yada klasik Object , bir base/ana prototype e sahip olduğu için key/value anlamında Collection olarak bazı yan etkilere sahip.

Bir başka önemli noktada, örneğin Set için, key olarak ister string ister number hatta function bile kullanabilmemiz. Kısacası, eğer Collection olarak bir veri türüne ihtiyacınız varsa, set yada map ilk tercihimiz olmalı.

Template literals – String Dönüşümü için yeni bir alternatif.

Şimdiye kadar aşağıdaki gibi bir kullanımla, javascript içinde string oluşturma yada değişkenleri mevcut bir stringe ekleme yapıyorduk;

 

let isim = "Ali";
let soyad = "Korkmaz";
let sinif = "3A";
const Ogrenci = isim + ' ' + soyad + " , Sinif :  "+sinif;
console.log(Ogrenci)
//Ali Korkmaz , Sinif :  3A

+ operatörü ile string ve değişkenleri bir birine eklediğimiz bu model den (bunun dışınd abir iki model daha olsada, onlarda aynı şekilde uzun bir yazım düzenine sahip ) yeni bir modele , ES6 ile gelen Template literals :  `${}` geçmiş olduk.  Template Literal için string tanımlamımızın;

  1. backtick(ters tirnak)   ` ile baslayip ` yine backtick ile bitmesi lazim.
  2. Metin içine gömmek istediğimiz değişkenleri yada her hangi bir javascript kodunu
    1. ${} / dolar ve süslü parantez içine almamız yeterli
  3. Ayrıca, multi-line / bir den çok satırda yazma imkanıda sunulmakta.

Yukarıdaki örneği template literal ile yeniden yazacak olursak:

const Ogrenci =`${isim} ${soyad} , Sinif :  ${sinif}`;

console.log(Ogrenci)
//Ali Korkmaz , Sinif :  3A

şeklinde tekrar yazabiliriz. İşin bir diğer güzel tarafıda, birden fazla satır da yazmak istersek (Angular daki @Component decorator ünü ve html yada css i dahili yazma imkanımızı düşünün) string literal ile kolayca bu isteğimizi yerine getirebilmekteyiz. Örneğin,

import { Component, Input } from '@angular/core';

@Component({
 selector: 'my-hero-detail',
 template: `
    <div *ngIf="hero">
     <h2>{{hero.name}} details!</h2>
     <div><label>id: </label>{{hero.id}}</div>
    <div>
    <label>name: </label>
    <input [(ngModel)]="hero.name" placeholder="name"/>
   </div>
 </div>
`
 })
 export class HeroDetailComponent {
 }

yukarida string literal ile birden fazla satirda yazim ornegini goruyoruz.

Spread Operator and Rest Parameters

ES6/ES7 ile gelen en önemli yeniliklerden olan bu iki kavram ilk başta biraz karışık gelebilir. İki kavramından “” (3 nokta) ile kullanılması da bu karışıklığa biraz daha katkı yapmakta.  Ama pratikde bize kazandırdıklarına bakarak devam edersek sanırım daha rahat anlayabiliriz. İlk olrak Rest Parameters olarak anılan ve türkçeye ” kalan tüm parametreler”  diye çevşrebileceğimiz Rest Params a bakalım.

Rest Parametreleri ilk olarak, fonksiyonlara sayı sınırı olmadan parametre geçebilmemize imkan vermekte. Bundan önceki Javascript sürümlerinde de bu imkanımız olsada(arguments ), ES6 ile birlikte rest parametreleri bu işi standart ve daha kolay kullanılabilir hale getirmiş durumda.

Önceden, javascript de fonksiyon parametrelerinin yanı sıra, her fonksiyon için sağlanan arguments  isimli bir değişkeni kullanarak bir kaç eksta işlemle, beklediğimizden daha fazla parametre alıp almadığımız yada , toplamda kaç parametre geldiğini öğrenme imkanımız vardı. Fakat bu yöntem, ekstra işlemler gerektirmekteydi, örneğin, arguments  değişkenini önce bir diziye çevirip sonra işlem yapılırdı , yada arguments  nesnesi içinde 0. indeks değilde 1. index ile işleme başlamamız vs gibi küçük detaylar vardı vs.

rest parametrelerini anlamak adına, simdi bir örnek yapalım, bir fonksiyonumuz olsun, bu fonksiyon ilk parametre oalrak aldığı değeri, sonraki parametrelerle çarpıp bize toplamı döndürsün.  Örneğin,

function topla(carpan=1, sayi1,sayi2,sayi3) {
    let toplam = 0;
    toplam = (carpan * sayi1) + (carpan * sayi2) +(carpan * sayi3)
    return toplam;

}

console.log(topla(3,2,5,6)) // 39

Yukaridaki fonksiyonu, 4 den az veya fazla sayıda parametre ile çağırırsak ne olur? Yada belirli bir sayıda parametre değil dilediğimiz sayıda parametreyi işyebilir hale getirmek istersek? İşte rest paramsın bize getirdiği kolaylık burda kendini göstermekte. Örneğin yukarıdaki örneği, rest parametresi ile yeniden yazacak olursak;

function topla(carpan=1, ...sayilar) {
    let toplam = 0;
    sayilar.forEach(s => toplam += s * carpan)
    return toplam
}

console.log(topla(3,2,5,6)) // 39

parametre olarak toplamda 2 değişken kullanmış olduk, ikinci parametremizi bir rest parametresi olarak tanımladığımız için, otomatik olarak bir diziye(Array) dönüştürüldü, ve dinamik bir şekilde kullanma imkanımız oldu. Şimdi fonksiyonumuzu dilediğimiz sayıda parametre ile çağırabiliriz. Örneğin

console.log(topla(3,2,5,6,8,9,10)) // 120  gibi. Burada dikkat etmemiz gereken bir kaç hususu belirtmekte fayda var. İlk olarak, …rest parametremiz, en son parametre olmalı. Aşağıdaki gibi bir kullanım hataya neden olacaktır.
function topla(carpan=1, ...sayilar, baskaBirParametre=5 ) {
        ...
}

böyle bir kullanımda, şöyle bir hata alarız.  ” SyntaxError: Rest parameter must be last formal parameter ” . Ayrıca sadece bir tana rest parametresi kulllanabiliriz. Bir başka kısıtlamada, Object(nesne) içinde kullanacağımız “setter” içinde rest parametreleri kullanamayacak olmamız. Aşağıdaki bir kullanım hataya sebeb olacaktır.

let object = {
    // Syntax error: Can't use rest param in setter
    set name(...value) {
        // do something
    }
};

 

Spread Operator

Tıpkı, Rest parametreleri gibi aynı tanımlama şekli kullanılsada “ … “(üç nokta) , rest parametrelerimiz teoride yaptığı şeyin tersi durumlar için kullanabileceğimiz yeni bir operatör …spread .  İki operatör arasındaki bir diğer farkımız da, rest operatörleri sadece fonksiyon parametresi olarak kullanılabilirlen, …spread çok daha geniş bir kullanıma sahip.

Öncelikle bir hatırlatma yaparak devam edelim, bir önceki başlıkda “rest parametreleri” kullanımında dikkat ettiyseniz, parametrelerden bir diziye dönüşüm söz konusuydu. …spread ise genel olarak bunun tersi, collection/diziler den parametreye dönüşüm için kullanılmakta. Örneğin, elimizdeki bir dizi parametreyi bir fonksitona geçmek istediğimizi düşünelim,

function myFunction(x, y, z) { }
let params = [0, 1, 2];
myFunction(...params); // same as myFunction(0,1,2)

params dizisini, her hangi başka bir işlem yapmadan, fonksiyonumuza spread operator oalrak geçmemiz yeterli oldu. Böylece fonksiyonumuza bir dizi değil, dizinin içindeki elemanları tek tek parametre olarak atayabildik. Bir başka kulllanım örneğinde, dizi elemanları üzerindeki işlemlerde (ekleme, lat küme alma vs. ) bir çok kolaylık sağlaması.

Örneğin aşağıdaki gibi diziyi birleştirmek isteyelim,

let parts = ['shoulders', 'knees']; 
parts lyrics = ['head', ...parts, 'and', 'toes']; 
// ["head", "shoulders", "knees", "and", "toes"]

ilk dizimiz parts , ikinci dizimize belirlediğimiz noktadan itibaren eklenmiş oldu.  yad aaşağıdaki gibi bir kullanımka , iki farklı diziyi birleştirip 3.cü yeni bir dizi elde edebiliriz.

let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];
//[ 0, 1, 2, 3, 4, 5 ]
const x = ['a', 'b'];
const y = ['c'];
const z = ['d', 'e'];

const arr = [...x, ...y, ...z]; // ['a', 'b', 'c', 'd', 'e']

 

ES6 ile Javascript e gelen yeniliklere bakmaya çalışdığımız bu yazıda, aşağıdaki 3 konu yu bilerek sonraki yazılara bıraktım:

  1. Asenkron yapıdaki yenilikler
    1. Promise
    2. async/await
  2. Modül sistemi
    1. import/export

Yukarıdaki iki başlığı ayrı olarak ele almak daha faydalı olacaktır,  ayrıca TypeScript konusunda da bu iki başlığa atıfda bulunacağız. O yüzden bu yazıyı burada bitirelim.

Kaynaklar:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference

http://exploringjs.com/es6/index.html#toc_ch_core-features

https://leanpub.com/understandinges6/read

 

2 thoughts on “ES6 / ES7 ile Javascript e gelen yenilikler

Leave a Reply to yazilimgunlugu Cancel reply

Your email address will not be published. Required fields are marked *