Teknik Detaylar

ES13 nedir? ECMAScript 2022 nedir?

← Teknik Detaylar
2026-06-20 · 4 dk okuma
ES13 nedir? ECMAScript 2022 nedir?
Bu yazıyı yapay zekâ ile tartış
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 (/d bayrağı 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ı)