JavaScript’te “getter” ve “setter” Metotları Kullanımı
Bu yazımızda, JavaScript’te bir nesnenin özelliklerine erişmek ve değiştirmek için kullanılan “getter” ve “setter” metotları hakkında bilgiler vereceğiz.
JavaScript’te “getter” ve “setter” Metotları
“getter” ve “setter” metotları, 2009 yılında yapılan ECMAScript 5 (ES5) sürümünde JavaScript’e eklenmiştir. Özellikle Java ve C# gibi programlama diillerine hakimseniz bu özelliklerin sahip olduğu çalışma mantığına aşina olabilirsiniz.
Yalnız belirtmek isterim ki, bu özellikller aslında dile yeni bir işlevsellik eklemezler. Bilakis daha okunabilir veya ifade edilebilir kod yazmamıza olanak tanıyan “syntactic sugar” (sözdizimsel şekerleme) olarak adlandırılan bir özelliktir.
Bu metotlar, genellikle sınıfın dışından değiştirilebilecek verinin miktarını sınırlamak ve böylece programın daha tahmin edilebilir olması için dile kazandırılmıştır.
Ayrıca belirtmek isterim ki, JavaScript’te bir nesnenin “getter” metodunu çağırırken ya da “setter” metodunu kullanırken parantez kullanmazsınız. “Getter” ve “setter” metotları normal metotlar gibi değildir; onlar bir özellik gibi davranır.
“getter” Metodu
Bir özelliğin değerini döndürmesi için kullandığımız metottur. “get” anahtar kelimesi ve bir fonksiyonun birleşiminden oluşur. Nesnenin belirli bir özelliğine erişildiğinde otomatik olarak çağrılır. Yani bir nesne özelliği için bir “getter” tanımlamak için, özelliğin adını ve bir fonksiyonu “get” anahtar kelimesi ile birlikte kullanmamız gerekir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class Circle { constructor(radius) { this._radius = radius; } // Getter metodu get area() { return Math.PI * this._radius * this._radius; } // Normal bir fonksiyon circumference() { return 2 * Math.PI * this._radius; } } // Circle sınıfından bir nesne oluşturma let circle = new Circle(5); // area getter'ını çağırma console.log(circle.area); // Yaklaşık olarak 78.53981633974483 // circumference fonksiyonunu çağırma console.log(circle.circumference()); // Yaklaşık olarak 31.41592653589793 |
Yukarıdaki örneğimizde, circle.area
ile circle.circumference()
arasındaki farkı görmüşsünüzdür diye düşünüyorum. “Getter” metodu olan area
parantez kullanmadan çağrılırken, normal bir fonksiyon olan circumference
ise parantez ile çağrılmıştır.
“Peki, niye böyle bir şey kullanıyoruz?” diye sorabilirsiniz. JavaScript’teki “getter” metodu, bir nesne özelliğinin değerini “get” (alan) eden, yani döndürmek için kullanılan bir metoddur ve bir nesne özelliğine erişirken (yani değerini okurken) otomatik olarak tetiklenir. Örneğin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Rectangle { constructor(width, height) { this.width = width; this.height = height; } // area is a computed property using a getter get area() { return this.width * this.height; } } let rect = new Rectangle(10, 5); console.log(rect.area); // 50 |
Bu örnekte, area
hesaplamalı bir özelliktir. Yani, width
ve height
özelliklerinin değerlerine dayanarak hesaplanır. Her ne kadar doğrudan bir değeri saklamasa da, getter metodu sayesinde bir özellik gibi erişilebilir hale gelmiştir.
Bunu şöyle düşünebilirsiniz: “Getter”, bir özellik gibi davranan bir fonksiyondur. Ancak, bu “özellik”, gerçekte nesnenin durumunda saklanan değil, getter’in çalıştığı zaman hesaplanan bir değeri temsil eder.
Özetle, get
metodu bir anlamda bir fonksiyonun return
ifadesine benzer, ancak bir nesne özelliğine doğrudan erişimle otomatik olarak çalışır.
“setter” Metodu
Bir özelliğin değerini değiştirmek için kullanılan bir metoddur. “set” anahtar kelimesi ve bir fonksiyonun birleşiminden oluşur. Belirli bir nesne özelliğine değer atandığında otomatik olarak çağrılır.
İlk örneğimizi içinde “setter” metodu olacak şekilde güncelleyelim:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
class Circle { constructor(radius) { this._radius = radius; } // Getter metodu get area() { return Math.PI * this._radius * this._radius; } // Setter metodu set radius(value) { if (value <= 0) { console.log("Yarıçap pozitif bir değer olmalıdır!"); return; } this._radius = value; } // Normal bir fonksiyon circumference() { return 2 * Math.PI * this._radius; } } // Circle sınıfından bir nesne oluşturma let circle = new Circle(5); // area getter'ını çağırma console.log(circle.area); // 78.53981633974483 // circumference fonksiyonunu çağırma console.log(circle.circumference()); // 1.41592653589793 // radius setter'ını kullanma circle.radius = 10; // Yarıçapı 10 olarak ayarla // Yeniden area getter'ını çağırma console.log(circle.area); // Yeni yarıçapa göre hesaplanmış alan değeri: 314.1592653589793 |
Bu örnekte, radius
adında bir setter metodu ekledik. Bu setter, radius
özelliğine bir değer atanmaya çalışıldığında otomatik olarak çalışır. Özellikle, eğer atanmaya çalışılan değer 0’dan küçük veya eşitse, bir hata mesajı gösterir ve yarıçapı değiştirmez. Bu da demektir ki, bir nesne özelliğine değer atanırken ek kontroller veya işlevsellik eklememize olanak tanımaktadır.
Bu şekilde, “getter” ve “setter” metotları, bir nesnenin özelliklerine erişim ve değişiklik yapmanın kontrollü bir yolunu sağlar. Bu özellikler genellikle birlikte kullanılır ve bir nesnenin özelliklerini korumak, doğrulamak ve özelleştirmek için etkili bir yol sunar.
Bir bakıma set
metodu, bir değişkenin değerini ayarladığınızda kullandığınız atama operatörüne (=
) benzer. Ancak setter
metotları, bir değişkenin değerini doğrudan ayarlamak yerine, bir özellik üzerinde daha fazla kontrol sağlamak için kullanılır.
JavaScript’te “getter” ve “setter” Kullanma Nedenleri
Underscore (_
) karakteri, genellikle bir özelliğin veya değişkenin “private” (yani sadece belirli bir kapsam veya sınıf içinden erişilebilir) olduğunu belirtmek için kullanılır. JavaScript, varsayılan olarak gerçek private özellikleri desteklemez (yani, belirli bir kapsam veya sınıf dışından erişilemez), bu yüzden geliştiriciler genellikle bu tür bir değişkenin doğrudan erişimini ve değiştirilmesini sınırlamak için _
ön eki kullanırlar.
Bu durumda, getter
ve setter
metotları, bu “private” özelliklere erişmek için güvenli bir yol sağlar. Bu metotlar, bir nesnenin özelliklerini kontrol etmek ve yönetmek için kullanılır. Aşağıda bunların genel kullanım amaçlarından bazıları bulunmaktadır:
- Veri Doğrulama: Setter metotları, bir özelliğe atanacak değerleri doğrulamak ve filtrelemek için kullanılabilir. Örneğin, bir nesnenin
age
özelliğini ayarlamak için bir setter oluşturabilir ve yalnızca geçerli bir yaşın atanmasını sağlayabilirsiniz. - Veriye Kontrollü Erişim: Getter ve setter metotları, bir nesnenin özelliklerine kontrollü erişim sağlar. Bu, bir özelliğin doğrudan değiştirilmesini önlemeye ve özelliği okumadan önce ek işlemler yapmaya yardımcı olur.
- Veri Gizleme ve Özelleştirme: Getter ve setter metotları, bir özelliğin iç uygulama detaylarını gizlemek ve bir nesnenin dış arayüzünü özelleştirmek için kullanılabilir. Bu, uygulamanın farklı bölümlerini birbirinden izole eder ve kodun daha güvenli ve bakımı daha kolay hale gelir.
- Bilgi Saklama ve Daha Fazla Fonksiyonalite: Getter ve setter metotları, bilgi saklama (encapsulation) prensibini uygulamanın bir yoludur. Bu, bir nesnenin durumunu ve davranışını bir arada tutarak kodun daha düzenli ve anlaşılır olmasını sağlar. Ayrıca, bir özelliğe erişim veya değiştirme işlemi sırasında ek işlevler çalıştırmak için kullanılabilirler.
❗ Getter ve setter metotlarını kullanırken akılda tutulması gereken başka bir şey, özelliklerin “getter” ve “setter” metotlarıyla aynı adı paylaşamayacağıdır. Aksi takdirde, bu durum bir sonsuz döngüye (infinite loop) veya sonsuz çağrı yığınına (call stack error) neden olabilir. Örneğin:
1 2 3 4 5 6 |
let person = { firstName: 'John', get firstName() { return this.firstName; } }; |
Bu durumda firstName
özelliği ve firstName
getter
metodu aynı isme sahip. Bu nedenle, person.firstName
ifadesini çağırdığınızda, getter
metodu this.firstName
ifadesini çağırır. Ancak this.firstName
, aslında getter
metodunu temsil ettiği için, getter
metodu kendini tekrar çağırır. Bu, bir sonsuz döngüye neden olur.
Bu tür bir durumun önüne geçmek için, genellikle bir _
(alt çizgi) karakteri ekleyerek getter
ve setter
metotlarından farklı bir isimle özelliği adlandırabiliriz.
Aşağıdaki örneğimizde bir Person
nesnesi oluşturacağız ve firstName
, lastName
ve age
özellikleri için getter ve setter metotları kullanacağız. Ayrıca veri doğrulama ve ek işlevlerin nasıl çalıştığını da göstereceğiz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
// let Person = { _firstName: '', _lastName: '', _age: 0, get firstName() { return this._firstName; }, set firstName(name) { if (typeof name === 'string' && name.length > 0) { this._firstName = name; } else { console.error("First name must be a non-empty string."); } }, get lastName() { return this._lastName; }, set lastName(name) { if (typeof name === 'string' && name.length > 0) { this._lastName = name; } else { console.error("Last name must be a non-empty string."); } }, get age() { return this._age; }, set age(years) { if (typeof years === 'number' && years >= 0 && years <= 120) { this._age = years; } else { console.error("Age must be a valid number between 0 and 120."); } }, get fullName() { return `${this.firstName} ${this.lastName}`; }, set fullName(fullName) { let parts = fullName.split(' '); if (parts.length === 2) { this.firstName = parts[0]; this.lastName = parts[1]; } else { console.error("Full name must consist of a first name and a last name."); } } }; // Using the setters Person.firstName = 'John'; Person.lastName = 'Doe'; Person.age = 25; console.log(Person.firstName); // John console.log(Person.lastName); // Doe console.log(Person.age); // 25 console.log(Person.fullName); // John Doe // Attempt to assign invalid values Person.firstName = ''; Person.lastName = 123; Person.age = 130; // these will throw errors // Using the fullName setter Person.fullName = 'Jane Smith'; console.log(Person.firstName); // Jane console.log(Person.lastName); // Smith |
Yukarıdak örnekte, firstName
, lastName
ve age
için getter ve setter metotları belirledik. fullName
özelliği için ek bir getter ve setter metodu ekledik. fullName
setter’ı, fullName
özelliğine bir değer atandığında firstName
ve lastName
özelliklerini de ayarlar.
“Setter” metotları ayrıca veri doğrulama gerçekleştirir. Yani, firstName
ve lastName
‘in geçerli bir string olduğunu, age
‘in ise 0 ile 120 arasında bir sayı olduğunu kontrol ederler. Geçerli olmayan bir değer ayarlamaya çalıştığınızda bir hata mesajı gösterirler.