ES5 Aralık 2009’da yayınlanan 5. ECMAScript sürümüdür. Haziran 2011’de 5.1 güncellemesini almıştır.

ES5 ile yeni neler geldi ?

ES5 javascripte köklü değişiklikler getirdi. Ardından gelen ES6 ile birlikte modern javascriptin kapılarını açmış oldu. ES5 2009 yılında şu yenilikleri getirdi;

  • Strict Mode
  • Erişim ve atama (Getter ve Setter) metotları
  • Rezerve kelimeler ve anahtarlar (Reserved Words & Property Keys)
  • String.prototype.CharAt();
  • Object.defineProperty()
  • Object.keys()
  • Object.getOwnPropertyNames()
  • Object.create();
  • Array.isArray()
  • Array.forEach()
  • Array.map()
  • Array.filter()
  • Array.reduce()
  • Array.every()
  • Array.indexOf()
  • Array.lastIndexOf()
  • Date.now()
  • Date.prototype.toISOString();
  • JSON.parse()
  • JSON.stringify();
  • …..prottype.toJSON();
  • Function prototype.bind()
  • Legal trailing commas
  • Multiline string literals
  • Object.getPrototypeOf(), Object.getOwnPropertyDescriptor(), Object.preventExtensions(), Object.isExtensible(), Object.seal(), Object.isSealed(), Object.freeze(), Object.isFrozen()

Strict Mode / Use Strict

'use strict';

Yukarıdaki satırı js dosyanızın ilk satırına koyarsanız strict mode’u etkinleştirmiş olursunuz. Bu mod standart dışı bazı kullanımlara sınır getirir, daha katı kontroller yapar ve daha çok istisna (exception) fırlatır. Neden başımıza dert alıyoruz? Daha temiz ve standart bir kod yazmak için.

Erişim ve Atama metotları (Getters and Setters)

Getter ve Setter olarak adlandırılan erişim ve atama metotları ile bir nesnenin niteliklerini-özelliklerini bu metotlar vasıtasıyla alabiliyor veya atabiliyorsunuz. Örneğin;

var user = {
  firstName: "John",
  lastName : "Doe",
  _role    : "admin",
  isAdmin  : {
    get: function() { return ( this.role === "admin") },
    set: function(value) { this.role = ( value ?? "admin" : "user"); },
  },
};

Getter ve Setter kullanmanın avantajları, anlaşılması kolay kodlar yazmanızı sağlar, veri okuma ve yazmayı daha kontrollü hale getirir, arka planda istediğiniz işlemi yapmanızı sağlar. ( Örneğin bir nesneye hem değeri güncelleyecek, hem de ajax ile sunucuya yeni değeri otomatik olarak gönderecek bir setter yazabilirsiniz. )

Rezerve kelimeler ve anahtarlar (Reserved Words & Property Keys)

var, new, function vs. gibi reserve kelimeleri değişken adı olarak kullanamıyoruz, ES5’e kadar nesne özellikleri için anahtar olarak da kullanamıyorduk. ES5 ile birlikte rezerve kelimeler nesne anahtarı olabiliyor.

var car = { old: "Tosbaga", new: 'Beetle', function: 'Aile Arabası' };

String.prototype.charAt()

charAt() metodu ile bir stringing belirli bir indeksindeki karakteri alabiliyoruz.

var str = "Merhaba Dünya";
console.log( str.charAt(0) ); // M
console.log( str.charAt(8) ); // D

object.defineProperty()

ES5 ile yeni property metotları sayesinde nesnelerimiz için yeni property’ler belirleyebiliyor veya mevcut olanları değiştirebiliyoruz. Bu atamayı direk yapabiliyorken object.defineProperty() neden kullanılır? object.defineProperty metodu değerle birlikte, bu property’nin alt özelliklerini de ayarlamanıza olanakj verir. (örneğin writable, enumerable vs. gibi)

const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false,
  enumerable: true,
});

object1.property1 = 77;
// strict.mode açıkken hata alırsınız, çünkü nesne yazma korumalı

console.log(object1.property1);
// konsola 42 yazılır


// Kaynak: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperties() metodunu kullanarak nesneye eklenecek yeni property’leri topluca ekleyebilirsiniz.

Object.defineProperties(object1, { 'property1' : { ..... }, 'property2': {......} });

Object.keys()

Bir nesneye ait özellik anahtarlarını (enumarable olanları) array şeklinde döndürür

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// beklenen çıktı: Array ["a", "b", "c"]

//Kaynak: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Object.getOwnPropertyNames()

Object.keys’e benzer şekilde bir nesneye ait özellik anahtarlarını döndürür. Object.keys’den farkı enumerable olmayan anahtarları da döndürmesidir. (Symboller hariç)

Object.create()

Object.create var olan bir nesneyi prototip olarak kullanarak yeni bir nesne oluşturur.

const person = {
  isHuman: false,
  printIntroduction: function() {
    console.log(`Benim adım ${this.name}. Ben insan mıyım? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = 'Matthew'; // "name" özelliği "me" nesnesinde var fakat" person" da yok
me.isHuman = true; // asıl nesneden gelen özellikler değiştirilebilir

me.printIntroduction();
// beklenen çıktı: "Benim adım Matthew. Am I human? true"

// Kaynak: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

Array.isArray()

Array.isArray() ile bir nesnenin (değişkenin) array tipinde olup olmadığını test edebilirsiniz.

var carBrands = ["Renault", "Toyota", "Honda", "Mercedes"];
console.log(Array.isArray(carBrands));

Array.prototype.forEach()

forEach metodu belirtilen bir fonksiyonu (callback) Array’in tüm elemanları için çağırır.
Callback fonksiyonuna ek olarak, bu fonksiyon içerisinde “this” değerine karşılık gelecek nesneyi de ayrıca gönderebilirsiniz.

Callback fonksiyona 3 parametre gönderilir,

element: O anda işlenen eleman. (mecburi)
index: Elemanın array içerisindeki indeksi (isteğe bağlı)
array: forEach’in çağırıldığı orijinal array

// Arrow function kullanarak çağırma
forEach((element) => { ... } )
forEach((element, index) => { ... } )
forEach((element, index, array) => { ... } )

// Callback fonksiyonu vererek çağırma
forEach(callbackFn)
forEach(callbackFn, thisArg)

// Satır içi callback fonksiyonu ile çağırma
forEach(function callbackFn(element) { ... })
forEach(function callbackFn(element, index) { ... })
forEach(function callbackFn(element, index, array){ ... })
forEach(function callbackFn(element, index, array) { ... }, thisArg)

// Kaynak: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Array.prototype.map()

Array.map fonksiyonu çağırıldığı array’deki elemanların her biri için bir callback fonksiyonu çağırır ve bunlardan dönen değerlerin tümünü yeni bir array olarak döndürür.

Array.map’e verilen callback fonksiyonuna 3 parametre gönderilir;

  • Çalışılan öğenin değeri (zorunlu)
  • Çalışılan öğenin indeksi (isteğe bağlı)
  • Çalışılan orijinal Array (isteğe bağlı)

Callback fonksiyonunu foreach’de olduğu gibi çeşitli şekillerde tanımlayabiliriz. Bunun dışında kullanımı basitçe şöyledir;

var oldSalaries = [1000, 1500, 1800, 2300];
var newSalaries = oldSalaries.map(function(val) {
    return val * 1,20;
});

// Herkese %20 zam, [1200, 1800, 2160, 2760]

Array.prototype.filter()

Array.filter fonksiyonu, bir arraydeki tüm elemanlar için verilen callback fonksiyonunu çalıştırır ve döndürdüğü değere göre (true ya da false) ilgili elemanı döndüreceği değere ekler ya da eklemez.

Callback fonksiyonuna gönderilen parametreler Array.Map ile aynıdır. Callback fonksiyonu önceki örneklerdekine benzer şekilde farklı yöntemlerle tanımlanabilir.

var salaries = [1000, 1500, 1800, 2300];
var lowSalaries = salaries.filter(function(val) {
    return val < 2000
});

// Maaşı 2000'den düşük olanların maaşları [1000, 1500, 1800]

Array.prototype.reduce()

Array’in her elemanı için çalışan bir callback ile sonunda tek bir değer elde etmeyi sağlar. Esasen bir iterasyon’da geri döndüreceğiniz değerin sonraki iteration’a parametre olarak gönderir.

Callback fonksiyonuna gönderilen parametrelerden ilki bir önceki iterasyondan dönen değer, geri kalanlar Array.Map ile aynıdır. Callback fonksiyonu önceki örneklerdekine benzer şekilde farklı yöntemlerle tanımlanabilir.

var failures = [12, 34, 18, 26];
var totalFailures = failures.reduce(myFunction);

function myFunction(total, value, index, array) {
  return total + value;
} 

// 4 oturumda toplam 90 hata gerçekleşmiş

Array.prototype.every()

Array’in tüm elemanları belirli bir koşulu sağlıyor mu test etmenizi sağlar. Bir nevi array filter ve array reduce’un birleşimidir. Tek bir array elemanı dahi koşulu sağlamıyorsa false değerini döndürür.

Callback fonksiyonuna gönderilen parametreler Array.Map ile aynıdır. Callback fonksiyonu önceki örneklerdekine benzer şekilde farklı yöntemlerle tanımlanabilir.

var ages = [12, 34, 18, 26];

var allOver18 = ages.every(myFunction);

function myFunction(value) {
  return value > 18;
} 

// Odadaki herkes 18 üzeri, reklamları buna göre gösterebiliriz.

Array.protoype.indexOf()

Bir değeri array içerisinde arar ve bulduğu ilk indeksi döndürür (bulunamazsa -1 döndürür)

İki parametre alır, ilki aranacak değer, ikincisi ise aramaya hangi indeksten başlanacağıdır. İkinci parametre verilemezse aramaya array’in başından (indeks 0) başlanır.

var ages = [12, 34, 18, 26];

var indexOf18 = ages.indexOf(18);

// indeks 2'de 18 yaşında biri bulundu

Array.protoype.lastIndexOf()

Bir değeri array içerisinde arar ve bulduğu ilk indeksi döndürür (bulunamazsa -1 döndürür). indexOf’dan farklı olarak aramaya array’in sonundan başlar.

Date.now()

Unix epoch’dan itibaren geçen süreyi (00:00:00 UTC 1 January 1970) milisaniye cinsinden verir.

// Başlangıç zamanını bir değişkene aldık
const start = Date.now();

// 2 saniye sonra çalışacak bir fonksiyon ayarladık
setTimeout(() => {
  // Başlangıçtan bu yana geçen milisaniye cinsinden süre
  const millis = Date.now() - start;

  console.log(`kaç saniye geçti ? -> ${Math.floor(millis / 1000)}`);
  // beklenen sonu: kaç saniye geçti? -> 2
}, 2000);

// Kaynak: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now

Date.prototype.toISOString()

Date tipindeki bir veriyi, ISO formatlı bir stringe dönüştürür.

const event = new Date('20 October 2021 13:00 GMT+03:00');
console.log(event.toString());
// beklenen sonuç: Wed Oct 20 2021 13:00:00 GMT+0300 (GMT+03:00)

console.log(event.toISOString());
// beklenen sonuç: '2021-10-20T10:00:00.000Z'

JSON.parse()

JSON formatındaki bir stringi ayrıştırarak nesneye dönüştürmenize yardımcı olur.

var obj = JSON.parse('{"name":"John Doe", "age":18, "city":"Amsterdam"}');

JSON.stringify()

Bir nesneyi json formatlı bir stringe dönüştürmenize yardımcı olur.

var obj = {
  name : "John Doe",
  age : 18,
  city : "Amsterdam",
}

var objJSON = JSON.stringify(obj); 

Function.prototype.bind

function.prototype.bind ES5 öncesinde eksikliği çok duyulan ve dolaylı (ve birazda kirli) yollarla çözülmeye çalışılan bir sorunu çözdü. “this” anahtarının fonksiyon içerisinde alacağı değeri parametre olarak verebilmemizi sağlıyor.

(Örn. SetTimeOut fonksiyona vereceğiniz bir callback fonksiyonu için kurtarıcı olabilir)

const module = {
  x: 42,
  getX: function() {
    return this.x;
  }
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // Fonksiyon global scope'da çağrıldığı için içerisindeki this anahtarı tanımsız
// beklenen çıktı: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// beklenen çıktı : 42

Trailing Commas

ES5’e kadar bir array ya da nesnenin içeriğini virgül ile sonlandıramıyorduk. Bu neden önemli? Eğer nesnenin son elemanından sonra virgül bırakırsanız, yeni bir eleman eklemek istediğinizde yeni bir satır oluşturmanız yeterli olur, önceki satırı değiştirmeniz (virgül eklemeniz) gerekmez. Bu özellikle sürüm kontorlü sistemlerinde daha temiz bir görünüm için faydalı olacaktır.

Mutliline Strings

ES5’den önce bir stringi birden fazla satıra bölemiyorduk. ES 5 ile ters slash ( \ ) kullanarak çok satırlı hale getirebilmeye başladık.

var text = "foo \
bar"

Not: ES6 birlikte buna da gerek kalmadı ve ters tırnak ` içine yazdığımız stringler birden fazla satıra bölünebilir oldu. Fakat ben hala ters slash yöntemini daha pratik buluyorum.

Diğer

Bu yazıda detaylarına girmediğim ( yazı bu haliyle bile çok uzun oldu) , fakat ileri seviye kullanımlar için ilginç olabilecek Object.preventExtensions(), Object.isExtensible(), Object.seal(), Object.isSealed(), Object.freeze(), Object.isFrozen(), Object.getPrototypeOf(), Object.getOwnPropertyDescriptor() metotlarını da incelemenizi öneririm.

Bu Yazıda Yapılan Düzenlemeler
  • 11.05.2022: Başlıklardaki görsel hatalar düzeltildi. Özet bölümü düzenlendi.