JavaScript’te “new” Operatörü Kullanımı
Bu yazımızda, JavaScript’te “new” operatörü ne işe yarar, nasıl kullanılır gibi sorulara cevap verip bu operatörün nesne oluşturma süreçlerinde nasıl bir rol oynadığına dair detayları ele alacağız.
JavaScript’te “new” Operatörü
JavaScript’in ilk sürümünden beri olan “new” operatörü, nesne yönelimli bir programlama dili olan Java’dan esinlenerek oluşturulmuştur.
Ancak bu esinlenmenin yüzeysel kaldığını belirtmek isterim. Zira Java dilinde “new” operatörü bir sınıfın yeni bir örneğini oluştururken, JavaScript’te yapıcı bir fonksiyonun yeni bir örneğini oluşturur. İşte bu da JavaScript’i prototip tabanlı miras modeli kullanan bir dil yapar.
Yani bu demektir ki, JavaScript ve Java arasındaki benzer sözdizimleri ve terimler, her iki dilin altında yatan temel yapıların aynı olduğu anlamına gelmez. JavaScript’in prototip tabanlı miras modeli, Java’nın sınıf-tabanlı modelinden farklı bir yaklaşım sunar. Bu farklılık, objeler arasında ilişkilerin nasıl kurulduğu, mirasın nasıl işlediği ve yeni nesnelerin nasıl oluşturulduğu konularında ortaya çıkar. Bu yüzden, yüzeydeki benzerliklere rağmen, her iki dilin arkasındaki felsefe ve mekanizmalar oldukça farklıdır deyip konuyu JavaScript’te new operatörünün nasıl kullanıldığını gösterelim.
JavaScript’te “new” operatörünün kullanımı oldukça basittir ve temelde bir yapıcı fonksiyonun yeni bir örneğini oluşturmayı sağlar. Aşağıdaki örneği inceleyiniz:
1 2 3 4 5 6 7 8 |
function Araba(marka, model) { this.marka = marka; this.model = model; } var benimArabam = new Araba("Toyota", "Corolla"); console.log(benimArabam.marka); // "Toyota" console.log(benimArabam.model); // "Corolla" |
Yukarıdaki örneğimizde, Araba
adında bir yapıcı fonksiyon tanımladık. Ardından new
operatörüyle bu yapıcı fonksiyonu kullanarak yeni bir Araba nesnesi oluşturduk ve bunu benimArabam
değişkenine atadık. Oluşturduğumuz bu nesne, belirttiğimiz marka
ve model
özelliklerine sahiptir.
Örneğimizden de anlaşılacağı üzere yapıcı fonksiyonlar isimlendirme yapılırken baş harfi büyük bir “PascalCase” şeklinde yapılır.
Yukarıdaki örneğimiz yalnızca özellikler barındırmaktadır. Bir nesnenin yöntemlerini de pekala yapıcı fonksiyonda tanımlayabiliriz. Bakınız:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function Car(brand, model, year) { this.brand = brand; this.model = model; this.year = year; this.getAge = function() { var currentYear = new Date().getFullYear(); return currentYear - this.year; } } var myCar = new Car("Toyota", "Corolla", 2005); console.log(myCar.getAge()); // Bu kodun çıktısı, arabanın yaşını verecektir. // Çıktı 18 veriyor (2023 - 2005 = 18) |
Yukarıdaki örneğimizde, Car
yapıcı fonksiyonuna getAge
adında bir yöntem ekledik. Bu yöntem, arabanın kaç yaşında olduğunu hesaplamaktadır. Haliyle Car
nesnesi oluşturduğumuzda, oluşturduğumuz bu nesne, aynı zamanda getAge
yöntemine de sahip olacaktır.
❗ JavaScript’te bir yapıcı fonksiyonun new
ile çağrılmasında tipik olarak this
ile yeni bir nesne oluşturulur ve otomatik olarak bu nesne döndürülür. Ancak, yapıcı fonksiyonun kendisi belirli bir nesne döndürürse, o zaman new
operatörü tarafından otomatik olarak oluşturulan nesne yerine o nesne döndürülür.
JavaScript'te eğer bir fonksiyon bir nesne döndürüyorsa ve bu fonksiyon
— fatih kadir akın (@fkadev) June 7, 2023new
ile çağrılıyorsa, döndürülen nesne, fonksiyonun oluşturacağı ve döndüreceği nesnenin (prototype) yerine geçer. Ancak bu döndürülen nesne, fonksiyonun prototype nesnesine bağlanmaz. https://t.co/ALYWLAjKDj
Eğer yapıcı bir fonksiyonun kendisi belirli bir nesne döndürürse, ondan üretilen nesne, yapıcı fonksiyonun prototipine bağlanmaz. Yani, new operatörü kullanarak oluşturulan bir nesne, yapıcı fonksiyonun prototipine bağlanacağına, bizzat fonksiyonun içindeki nesne bu bağlantıya sahip olur. Örneğin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function Car(brand, model, year) { this.brand = brand; this.model = model; this.year = year; var anotherCar = { brand: "BMW", model: "X5", year: 2020 }; return anotherCar; } var myCar = new Car("Toyota", "Corolla", 2005); console.log(myCar); // Bu { marka: "BMW", model: "X5", yıl: 2020 } çıktısını verir. |
Yukarıdaki örneğimizde, new Car("Toyota", "Corolla", 2005);
kodu aslında bir Toyota Corolla 2005
nesnesi oluşturmak yerine, BMW X5 2020
nesnesini döndürmüştür. İşte tam da bu durum, Car
fonksiyonunun içinde anotherCar
nesnesini döndürdüğümüz için olmaktadır.
Özetle, JavaScript’te new
operatörü, belirli bir prototipi olan yeni bir nesne oluşturur ve bu nesneyi this
bağlamına ayarlar. O halde, yapıcı fonksiyonlarını new
operatörüyle çağırdığımızda neler olduğunu adım adım inceleyelim:
- Yeni bir nesne oluşturulur: İlk önce yeni bir boş nesne oluşturur ve yapıcı fonksiyonun prototipini miras alır.
this
bağlamı ayarlanır:this
anahtar kelimesi ile yeni oluşturulan nesne bağlanır. Yani, yapıcı fonksiyonun içindekithis
, oluşturduğumuz nesneyi kast eder.- Yapıcı fonksiyon çağrılır: Yeni oluşturulan nesne için
this
bağlamı ayarlanarak yapıcı fonksiyon çalıştırılır. Bu adımla beraber yapıcı fonksiyonun içindeki kod bloğu işletilmeye başlanır. - Yeni nesne döndürülür: Yapıcı fonksiyon başlatıldığında otomatik olarak yeni oluşturulan nesne döndürülür. Eğer yapıcı fonksiyon ayriyeten kendi nesnesine sahipse ve bunu döndürüyorsa,
new
operatörü bu nesneyi döndürür. Yani, yeni oluşturulan nesne yerine yapıcı fonksiyonun döndürdüğü nesne döndürülür.