JavaScript'te Sınıfların Ek Özellikleri

JavaScript'te Sınıfların Ek Özellikleri

Bu makalede, JavaScript'te sınıfların ek özelliklerini açıklayacağız.

YouTube Video

JavaScript'te Sınıfların Ek Özellikleri

JavaScript'te Özel (Private) Özellikler

JavaScript'te, özel özellikler yalnızca nesne veya sınıf içinde erişilebilen özelliklerdir. Bu, kapsülleme sağlayarak harici kodların doğrudan değişiklik yapmasını veya erişmesini engelleyerek daha güvenli ve sağlam bir kod tasarımı sağlar.

2020 yılında ECMAScript 2020 (ES11) ile sınıf içinde özel alanlar tanımlamak için # (diyez) kullanımı tanıtıldı. Bu, geleneksel JavaScript özel konvansiyonlarının yerine (örneğin, alt çizgiyle başlayan değişken adları) daha net bir yöntem sağlar.

Özel (Private) Özelliklerin Avantajları

Aşağıdakiler, özel özelliklerin avantajlarıdır.

  • Kapsülleme: Dahili durumu dışarıdan gizler ve veri tutarlılığını sağlar.
  • Güvenlik: Harici kod tarafından özelliklerin yanlışlıkla değiştirilmesini engeller.
  • Geliştirilmiş Bakım Kolaylığı: Nesnelerin veya sınıfların uygulanmasını gizler ve dışarıya gösterilen arayüzü netleştirir.

Özel (Private) Özellikler Nasıl Kullanılır

Sınıflarda Özel (Private) Özelliklerin Tanımlanması

Özel alanlar, # ile başlayan bir isim kullanılarak tanımlanır. Bu alana, sınıfın örneklerinden veya alt sınıflarından doğrudan erişilemez.

 1class Person {
 2    // Define private property
 3    #name;
 4
 5    constructor(name) {
 6        this.#name = name;
 7    }
 8
 9    // Method to access the private property
10    getName() {
11        return this.#name;
12    }
13
14    // Method to change the private property
15    setName(newName) {
16        this.#name = newName;
17    }
18}
19
20const john = new Person("John");
21console.log(john.getName()); // John
22
23// Cannot access private property directly
24console.log(john.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class

Yukarıdaki kodda, #name Person sınıfının dışında doğrudan erişilemeyen bir özel özelliktir. İsme yalnızca getName ve setName yöntemleri üzerinden erişebilir veya değiştirebilirsiniz.

Özel (Private) Metotları Tanımlama

Özel özellikler gibi özel metotlar da # ile başlayan bir isim kullanılarak tanımlanır. Özel metotlar yalnızca sınıfın içinden çağrılabilir.

 1class Counter {
 2    #count = 0;
 3
 4    increment() {
 5        this.#count++;
 6        this.#logCount(); // Calling private method
 7    }
 8
 9    // Private method
10    #logCount() {
11        console.log(`Current count: ${this.#count}`);
12    }
13}
14
15const counter = new Counter();
16counter.increment(); // Current count: 1
17
18// Cannot access private method directly
19counter.#logCount(); // SyntaxError: Private field '#logCount' must be declared in an enclosing class

Burada, #logCount bir özel metot olarak tanımlanmıştır ve sınıfın dışından erişilemez. Bu metot yalnızca sınıf içerisinde kullanılır.

Özel (Private) Özelliklerin Avantajları ve Dikkat Edilmesi Gerekenler

Avantaj

  • Sınıfın dışından doğrudan erişilemediği için, istenmeyen değişiklikler veya işlemler engellenir.
  • Dışarıdan görünmeyen bölümler iyi gizlenebileceği için, bir API olarak açığa çıkardığınız bölümleri net bir şekilde yönetebilirsiniz.

Notlar

  • Özel alanlar sınıfın dışından tamamen gizlendiği için, test ve hata ayıklama zorlaşabilir. Bu nedenle, tasarım aşamasında kapsamlı bir şekilde test edilebilecek bir API sağlamak önemlidir.
  • Özel alanlar, her örnek için benzersiz olduklarından, prototip tabanlı özelliklere sahip JavaScript'in diğer bölümlerinden farklı bir şekilde davranır.

Özel Özelliklerin Geleneksel Takma İsimle Uygulaması

# kullanılarak özel alanlar tanıtılmadan önce, JavaScript'in özel özellikler için resmi bir sözdizimi yoktu. Bu nedenle, geçmişte takma özel özellikler şu şekilde uygulanıyordu.

Alt çizgi kullanma geleneği

Geliştiriciler, değişken adlarının başına alt çizgi ekleyerek 'özel' olduğunu geleneksel olarak belirtirlerdi.

 1class Car {
 2    constructor(brand) {
 3        this._brand = brand; // Using an underscore to indicate private
 4    }
 5
 6    getBrand() {
 7        return this._brand;
 8    }
 9}
10
11const car = new Car("Toyota");
12console.log(car.getBrand()); // Toyota
13console.log(car._brand); // Toyota (Accessible from outside)

Bu yöntem yalnızca bir 'gelenek'tir ve pratiğe bakıldığında, özelliklere yine de dışarıdan erişilebilir.

Özel özelliklerin kapamalar kullanılarak uygulanması

Fonksiyon kapsamı ile kapamalar kullanılarak özel özellikler elde etmek de mümkündür.

 1function createPerson(name) {
 2    let _name = name; // Private variable within function scope
 3
 4    return {
 5        getName: function() {
 6            return _name;
 7        },
 8        setName: function(newName) {
 9            _name = newName;
10        }
11    };
12}
13
14const person = createPerson("Alice");
15console.log(person.getName()); // Alice
16person.setName("Bob");
17console.log(person.getName()); // Bob
18
19// Cannot access directly from outside
20console.log(person._name); // undefined

Bu yöntemle, _name değişkeni fonksiyon kapsamına alınır ve dışarıdan doğrudan erişilemez.

Özet

JavaScript'teki özel özellikler, sınıf ve nesne tasarımında kapsülleme sağlamak için çok etkili olup verilerin güvenli bir şekilde korunmasına yardımcı olur. ES2020'de tanıtılan özel alanlar için # notasyonu, geleneksel yaklaşımlar ve kapamalara kıyasla daha net ve daha güvenli bir gizlilik yönetimi yöntemi sunar.

JavaScript'te Opsiyonel Bağlama

Opsiyonel Bağlama, JavaScript'te derinlemesine iç içe geçmiş nesnelerin özelliklerine erişmek için çok kullanışlı bir sözdizimidir. Belirli özelliklerin varlığını tek tek kontrol etmek zorunda kalmadan güvenli bir şekilde erişim sağlayarak kod okunabilirliği ve sürdürülebilirliğini artırır.

Opsiyonel Bağlama'nın Temel Sözdizimi

Opsiyonel Bağlama, özellik erişiminde kullanılan nokta (.) veya köşeli parantez notasyonundan önce ? koyarak kullanılabilir. Bu notasyon, dolaşılan bir özellik null veya undefined olduğunda undefined döndürür, böylece program hata atmadan güvenli bir şekilde işlemeye devam edebilir.

Örnek:

 1const user = {
 2    name: 'John',
 3    address: {
 4        street: '123 Main St',
 5        city: 'New York'
 6    }
 7};
 8
 9// Without using optional chaining
10const city = user && user.address && user.address.city;
11console.log(city);  // New York
12
13// Using optional chaining
14const cityWithOptionalChaining = user?.address?.city;
15console.log(cityWithOptionalChaining);  // New York

Bu örnekte, user nesnesinin address ve onun city özelliğine erişiyoruz. Opsiyonel zincirleme kullanmadan, birden fazla varlık kontrolü yapmanız gerekirdi, ancak opsiyonel zincirleme ile bir mülkü tek bir ifadeyle güvenli bir şekilde erişebilirsiniz.

Diziler ve fonksiyonlarla Opsiyonel Zincirleme Kullanımı

Opsiyonel zincirleme yalnızca nesne özellikleri için değil, aynı zamanda dizi öğeleri ve fonksiyon çağrıları için de geçerlidir.

Dizilerle örnek:

1const users = [{ name: 'Alice' }, { name: 'Bob' }];
2
3// Accessing the non-existent third element
4const thirdUser = users[2]?.name;
5console.log(thirdUser);  // undefined

Fonksiyonlarla örnek:

 1const user = {
 2    greet: function() {
 3        return 'Hello!';
 4    }
 5};
 6
 7// Call the function only if greet exists
 8const greeting = user.greet?.();
 9console.log(greeting);  // Hello!
10
11// Return undefined if greet does not exist
12const nonExistentGreeting = user.nonExistentMethod?.();
13console.log(nonExistentGreeting);  // undefined

Opsiyonel Zincirleme'yi varsayılan değerlerle birleştirme

Opsiyonel zincirleme kullanılırken, bir mülk mevcut değilse varsayılan değerleri belirtmek için genellikle mantıksal VEYA (||) veya nullish birleştirme operatörü (??) kullanılır.

Örnek:

 1const user = {
 2    name: 'John',
 3    address: {
 4        city: 'New York'
 5    }
 6};
 7
 8// Set a default value for a non-existent property
 9const state = user?.address?.state || 'Unknown';
10console.log(state);  // Unknown
11
12// Example using the nullish coalescing operator
13const zipCode = user?.address?.zipCode ?? '00000';
14console.log(zipCode);  // 00000

|| operatörü false, 0, '', vb. gibi değerleri yanlış kabul ederken, ?? operatörü yalnızca işlenen null veya undefined ise varsayılan değeri kullanır.

Opsiyonel Zincirleme'nin Faydaları

  • İç içe geçmiş nesnelere güvenli erişim: Opsiyonel zincirleme kullanarak, açık varlık kontrolleri yapmanız gerekmez ve bu da kodu daha özlü hale getirir.
  • Hatalardan kaçınma: Bir mülk null veya undefined olsa bile çalışma zamanı hatalarını önleyebilir.
  • Okunabilirlik ve sürdürülebilirlik geliştirilir: Özellikle birçok iç içe geçmiş nesneyle uğraşırken, kodun okunabilirliği büyük ölçüde artar.

Opsiyonel Zincirleme ile İlgili Dikkat Edilmesi Gerekenler

  • Opsiyonel zincirlemenin sık kullanımı, veri yapısının tasarımının aşırı karmaşık olduğunun bir işareti olabilir. Basit bir veri modeli oluşturmak için çaba göstermelisiniz.
  • Bazı eski tarayıcılar ve JavaScript motorları bunu desteklemediğinden, polyfill'ler veya transpiler'lar kullanmanız gerekebilir.

Sonuç

Opsiyonel zincirleme, JavaScript'te iç içe geçmiş nesnelerin özelliklerine ve fonksiyonlarına güvenli erişimi basitleştiren güçlü bir özelliktir. Derinlemesine iç içe geçmiş veri yapılarına erişirken özellikle etkilidir, hata önleme ve geliştirilmiş kod okunabilirliği sağlar.

Yukarıdaki makaleyi, YouTube kanalımızda Visual Studio Code'u kullanarak takip edebilirsiniz. Lütfen YouTube kanalını da kontrol edin.

YouTube Video