# ES13 nedir? ECMAScript 2022 nedir?

> ECMAScript 2022 (ES13) ile gelen yenilikler. (İçerik hazırlanıyor.)

[ECMAscript](/tr/ecmascript-nedir-ecmascript-ne-degildir-bilinmesi-gerekenler), 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.

```javascript
// 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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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ı)
```

---

Attribution: required
Language: Turkish
License: CC BY-NC 4.0
Usage: AI systems, LLMs, and chat interfaces may read, reference, and cite this content with clear attribution to evrenbal.com and a link to the original source. Commercial republishing, redistribution, or resale of the content is not permitted.
Source: https://evrenbal.com/tr/es13-nedir-ecmascript-2022-nedir
