ES13 nedir? ECMAScript 2022 nedir?

Sayfayı kopyala
ECMAscript, kısa adıyla ES, Ecma-International tarafından ECMA-262 dokümanında yayınlanan ve her yıl yenilenen JavaScript standardıdır. Bu yazıda ECMAScript 2022 (ES13) sürümüyle gelen yenilikleri inceliyoruz.
ES13 (ECMAScript 2022), 2022 yılında yayınlanan 13. ECMAScript sürümüdür.
ES13 ile gelen yenilikler
ES13 ile birlikte tanımlanan yeni özellikler şunlar;
Top-level await(Modüllerde await kullanımı)- Class fields (Sınıflarda private, public ve static alanlar)
- Private metotlar ve accessor'lar (
#method) - Static class blocks (
static { ... }) - Ergonomik brand check (
#field in obj) .at()(Array, String, TypedArray için negatif indeksleme)Object.hasOwn()(Güvenli nesne özelliği kontrolü)- Error cause (
{ cause }parametresi ile hata izleme) - RegExp match indices (
/dbayrağı ile eşleşme indeksleri)
Top-level await
ES13 öncesinde, await anahtar kelimesini sadece async olarak tanımlanmış fonksiyonların içerisinde kullanabiliyorduk. Modüllerin en üst seviyesinde (top-level) asenkron işlemler gerçekleştirmek istediğimizde, kodumuzu geçici asenkron fonksiyonlarla (IIFE) sarmalamak zorunda kalıyorduk. ES13 ile birlikte artık JavaScript modüllerinin en üst seviyesinde doğrudan await kullanabiliyoruz.
// ES13 öncesi
(async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
})();
// ES13 sonrası (Modül dosyası içerisinde)
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
Class Fields (Sınıf Alanları)
Sınıf tanımlarında (class declarations) constructor fonksiyonu dışında doğrudan sınıf alanları (property'leri) tanımlayabiliyoruz. Üstelik bir alanın başına hash # işareti koyarak o alanı doğrudan private (dışarıdan erişilemez) hale getirebiliyoruz.
class Counter {
// Public alan
count = 0;
// Private alan (Sınıf dışından erişilemez)
#privateCount = 0;
increment() {
this.count++;
this.#privateCount++;
}
getPrivateValue() {
return this.#privateCount;
}
}
const myCounter = new Counter();
myCounter.increment();
console.log(myCounter.count); // 1
// console.log(myCounter.#privateCount); // Hata fırlatır!
console.log(myCounter.getPrivateValue()); // 1
Private Metotlar ve Accessor'lar
Private alan tanımlarını metotlara, getter ve setter fonksiyonlarına da uygulayabiliyoruz. Bir metodun veya getter/setter'ın başına # getirdiğimizde, o metot sadece sınıf içinden çağrılabilir hale geliyor.
class User {
name = "Evren";
// Private metot
#validateName(name) {
return name.length > 0;
}
// Private getter
get #fullName() {
return `${this.name} Bal`;
}
updateName(newName) {
if (this.#validateName(newName)) {
this.name = newName;
console.log(this.#fullName); // Sınıf içi erişim serbest
}
}
}
const user = new User();
user.updateName("Soruman"); // "Soruman Bal" çıktısını verir
// user.#validateName("Test"); // Hata fırlatır!
Static Class Blocks (Statik Sınıf Blokları)
Sınıfların statik alanlarını ilklendirmek (initialize) ve karmaşık konfigürasyonlar yapmak için static bloklar kullanabiliyoruz. Bu bloklar, sınıf ilk kez yüklendiğinde bir kez çalışır ve private alanlara da erişim yetkisine sahiptir.
class Configuration {
static dbUrl;
static #port = 5432;
static {
// Sınıf yüklenirken çalışacak karmaşık lojistik
const env = "PRODUCTION";
if (env === "PRODUCTION") {
this.dbUrl = `mongodb://prod:${this.#port}`;
} else {
this.dbUrl = "mongodb://localhost:27017";
}
}
}
console.log(Configuration.dbUrl); // "mongodb://prod:5432"
Ergonomik Brand Check
Sınıf içinde veya metotlarında, bir nesnenin belirli bir private alana sahip olup olmadığını güvenli bir şekilde kontrol etmek için in operatörünü kullanabiliyoruz. Buna "ergonomik brand check" deniyor.
class CacheReader {
#cache = {};
static isCacheReader(obj) {
// obj nesnesinin içinde #cache private alanı var mı kontrolü
return #cache in obj;
}
}
const reader = new CacheReader();
const plainObject = {};
console.log(CacheReader.isCacheReader(reader)); // true
console.log(CacheReader.isCacheReader(plainObject)); // false
.at() Metodu
Dizilerin (Array), metinlerin (String) ve TypedArray'lerin son elemanına veya sondan geriye doğru elemanlarına erişmek her zaman can sıkıcıydı. Klasik yöntemle arr[arr.length - 1] yazmak yerine, ES13 ile gelen .at() metodu sayesinde doğrudan negatif indeksler kullanabiliyoruz.
const colors = ['red', 'green', 'blue'];
// Son elemanı almak için
console.log(colors.at(-1)); // "blue"
// Sondan ikinci eleman için
console.log(colors.at(-2)); // "green"
const str = "evrenbal";
console.log(str.at(-1)); // "l"
Object.hasOwn()
Nesnelerin doğrudan kendisine ait bir özelliği (property) barındırıp barındırmadığını test etmek için geleneksel olarak hasOwnProperty metodunu kullanıyorduk. Ancak Object.create(null) ile oluşturulan nesnelerin prototipi olmadığından bu metot hata fırlatıyordu. ES13 ile gelen Object.hasOwn() statik metodu, bu kontrolü her nesne tipi için güvenli ve hatasız yapmamızı sağlar.
const user = Object.create(null);
user.age = 30;
// ES13 öncesi (Hata fırlatır)
// user.hasOwnProperty('age');
// ES13 öncesi güvenli yöntem (Uzun ve çirkin)
Object.prototype.hasOwnProperty.call(user, 'age'); // true
// ES13 sonrası (Kısa ve güvenli)
console.log(Object.hasOwn(user, 'age')); // true
Error Cause
Bir hatayı yakalayıp (catch) başka bir hata fırlatırken, asıl hatanın kaynağını (tüm stack trace detaylarıyla birlikte) kaybetmemek için yeni Error nesnesine { cause } seçeneğini ekleyebiliyoruz.
function connectDatabase() {
try {
// Olmayan bir servise bağlanmayı deneyelim
throw new Error("Connection Timeout");
} catch (err) {
// Hatanın asıl sebebini (cause) yeni hataya aktarıyoruz
throw new Error("Database initialization failed", { cause: err });
}
}
try {
connectDatabase();
} catch (error) {
console.log(error.message); // "Database initialization failed"
console.log(error.cause.message); // "Connection Timeout" (Asıl sebep)
}
RegExp Match Indices (/d Bayrağı)
Düzenli ifadelerde (RegExp) /d bayrağını (flag) kullandığımızda, eşleşen grupların metin içerisindeki başlangıç ve bitiş indekslerini içeren indices isimli bir dizi elde ederiz. Bu, metin editörlerinde veya parse işlemlerinde konum tespiti yaparken büyük kolaylık sağlar.
const regex = /evren/d;
const text = "Merhaba evrenbal";
const match = regex.exec(text);
// Eşleşmenin başlangıç ve bitiş indeksleri
console.log(match.indices[0]); // [8, 13] (e ve n harfleri arası)
