JavaScript’te Arrow Fonksiyon
Herkese merhaba, bu yazıda sizlere ES6 ile beraber gelen arrow function’dan bahsetmeye çalışacağım. Öncelikle bu yazının daha iyi anlaşılması için this kavramının iyi anlaşılmış olması gerekiyor.
İsteyen arkadaşlar buradan this ile ilgili yazdığım yazıya ulaşabilirler.
Öncesinde genel olarak fonksiyon konusunda bildiklerimizi biraz tekrar edelim. Fonksiyonları iki farklı şekilde belirtebiliyorduk, bunlardan biri function declaration diğeri function expression dediğimiz yöntem.
Yukarıdaki örneğe baktığımızda 2. satırda function declaration yöntemiyle bir fonksiyon oluşturduk ve num isminde bir değişken aldık num’ın karesini alıp 4 değerini return ediyor. 9. satırda function expression yöntemiyle oluşturduğumuz function da aynı görevi yaparak 9 değerini return ediyor. Daha önceki yazımda bu ikisi arasındaki farkları anlattığım için daha fazla detaya girmiyorum isteyenler buradan ulaşabilir. Şimdi bir de arrow function kullanarak konuya giriş yapalım.
Yukarıdaki örnekte ilk satırda arrow function expression yazıyor öncelikle bunu açıklayalım. Çünkü arrow fonksiyon daima function expression olarak yazılır. Function expression ise bir fonksiyonu bir değişkene atayarak veya bir ifade içinde tanımlayarak oluşturmamızı sağlar. Şimdi yukarıdaki arrow fonksiyonu inceleyecek olursak function keywordünden kurtulduğumuza dikkat etmişsinizdir. Yalnızca aldığımız parametreden sonra bir ok işareti kullanıyoruz. Yaptığımız en temel değişiklik bu, şimdi bir adım ileri daha gidelim.
Yukarıdaki örnekte 2. satıra bakacak olursak zaten tek bir satır olduğu için direkt olduğu satırı return ediyor gibi düşünebiliriz. O nedenle return’den ve süslü parantezlerden kurtuluyoruz yani 3. satırdaki şekli alıyor. Son olarak ek bir şey daha yaparız o da tek bir tane parametre aldığımız için normal parantezlerden de kurtuluruz. Böylece en sade şekli 4. satırdaki gibi olur. Bu arrow function ilk verdiğimiz örnekteki function declaration ve function expression ile aynı görevi yapıyor. Buraya kadar arrow function’ın daha çok syntax’ını inceledik. Şimdi biraz daha derinleşelim.
Arrow Fonksiyon - This İlişkisi
Öncelikle şu aklımızda bulunsun. Arrow function kullanmamızın tek sebebi daha özlü ve basit syntax’a sahip olması değil. Arrow function kullanmamızın en temel sebebi, arrow function’ın this ile olan ilişkisidir.
Şimdi direkt arrow function’ın this ile ilişkisine geçmeden önce regular fonksiyonların this ile olan ilişkisini biraz hatırlayalım.
Yukarıdaki örneğe baktığımızda 1. satırda window objesine bağlı bir name diye bir property tanımlıyoruz ve michael değerini veriyoruz. 3. satırda normal function declaration yöntemiyle tellName isminde bir fonksiyon oluşturuyoruz. Bu fonksiyonu 8. satırda çalıştırdığımızda ise 4. satırda window object, 5. satırda ise window’a bağlı olan name’i gösterdiği için michael çıktısını alıyoruz. Şimdi 10. satırda person adında bir obje oluşturduk bunun içinde tekrar tellName isminde bir fonksiyon oluşturuyoruz. Daha sonra bu fonksiyonun içindeki this’i ve this.name’i ekrana yazdıralım. 18. satırda person nesnesine bağlı olan tellName fonksiyonunu çalıştırdığımız zaman 13. satırdaki this person nesnesine bağlı dikkat ederseniz. 14. satırda this.name’e baktığımızda o nesneye bağlı olan name’i yani dwight’ı gösteriyor. Bunlar zaten beklediğimiz sonuçlar. Buradan şu çıkarımı yapabiliriz; Standart fonksiyon, this’i ilgili context içinde tanımlıyor. Yani 3. satırdaki fonksiyon window nesnesine bağlı olduğu için this, window nesnesini gösteriyor. Ancak 12. satırda tellName fonksiyonu person nesnesine bağlı olduğu için this, person nesnesini gösteriyor. Şimdi aynı örneği arrow function üzerinden yapalım.
Yukarıdaki örnekte 3. satırda normal fonksiyon değil de arrow fonksiyon kullandık. 8. satırda bu fonksiyonu çalıştırdığımızda this, window nesnesini gösteriyor ve doğal olarak da this.name’i de michael olarak ekranda görüyoruz. Buraya kadar ayını, normal fonksiyon ile arrow fonksiyon arasında pek bir fark yok gibi. Ancak 12. satırda person nesnesinin içinde tellName isminde bir fonksiyon oluşturduk. 18. satırda bunu çalıştırdığımzda ise dikkat ederseniz tekrar window nesnesini gösteriyor ve ona bağlı olarak this.name’i de michael olarak yazdırdı. Yukarıda ne demiştik? Standart fonksiyonlar this’i ilgili olduğu context’e göre gösterir. Ancak arrow fonksiyonların kendilerine ait bir this’i yoktur. Bu nedenle this’i bir dışarıdan alır. Yani 12. satırdaki tellName metodu fonksiyon olarak person nesnesine bağlı ancak kendine ait bir this olmadığı için bu objenin dışından alıyor. Bu dışarıdan aldığı yer window nesnesi olduğu için this, window nesnesini gösteriyor. Şimdi bir örnek daha yaparak this’i daha iyi anlamaya çalışalım.
Yukarıda yaptığımız örneği açıklayacak olursak bir tane person objesi oluşturuyoruz. Daha sonra bu nesnenin name’ine Dwight değerini veriyoruz sonrasında içine tellName adında bir fonksiyon yazıyoruz. Bu fonksiyon this’i ve this.name’i ekrana yazdıracak aynı bir önceki örnek gibi. Ancak bu fonksiyonun içerisine setTimout isminde farklı bir fonksiyon yazıyoruz. Bu setTimeout fonksiyonu da iki saniye sonra yine this’i ve this.name’i yazdırsın istiyoruz. 16. satırda tellName fonksiyonunu çalıştırdığımızda 6. ve 7. satırda this person nesnesini gösteriyor. Bu zaten bildiğimiz bir sonuç, çünkü bir nesnenin özelliği durumunda olduğu için this person nesnesine ait ve this.name’in değeri de dwight olarak bir çıktı alıyoruz. setTimeout’a baktığımızda içinde yeni bir fonksiyon yazdırıyor bu bambaşka bir fonksiyon olduğu için this’i default window nesnesi olarak algılıyor. Bunlar zaten beklediğimiz sonuçlar, şimdi bu örneği bir de arrow fonksiyon üzerinde görelim.
Şimdi yukarıdaki örneğe baktığımızda person nesnesi içindeki tellName’i arrow fonksiyona çevirdik. Ayrıca setTimeout’un içindeki fonksiyonu da arrow fonksiyona çevirdik. Şimdi 16. satırda tellName fonksiyonunu çağırdığımızda iki fonksiyonun da window nesnesini gösterdiğini görüyoruz. Neden? Çünkü tellName bir arrow fonksiyon, arrow fonksiyonlar için kendine ait bir this’i bulunmaz demiştik. Dolayısıyla this’i person’dan değil bir dışarıdan alarak window nesnesini gösterir. Daha sonra 9. satırda setTimeout içindeki de bir arrow fonksiyon ve kendine ait bir this’i yok bir sonraki tellName’e bakıyor o da bir arrow fonksiyon onun da kendine ait bir this’i olmadığı için bir üste yani window object’i gösteriyor. Genel kullanımla ilgili bir örnek verecek olursak;
Yukarıdaki örneğe baktığımızda 3. satırda tellName’i normal fonksiyon olarak tanımladık. Daha sonra setTimeout’un içindeki fonksiyonu arrow function şeklinde yazdık. Böylece tellName bir objenin fonkisyonu durumunda olduğu için this, person nesnesini gösteriyor. 7. satırdaki setTimeout içindeki arrow fonksiyonun kendine ait bir this’i olmadığı için dışarıdan alacak. Dışardan alacak olduğu o this de person nesnesini gösterdiği için this, direkt person nesnesini gösterecek. Bu sayede person nesnesi üzerinden işlem yapmaya devam edebiliriz. Bunun gibi bağlamın değişmesini istemediğimiz durumlarda arrow fonksiyonları kullanırız. Yukarıda da söylediğimiz gibi arrow function’ın en önemli özelliklerinden biri de this ile olan ilişkisidir.
Arrow Fonksiyon Constructor Olarak Kullanılamaz
Yukarıdaki örneğe baktığımızda biz constructor’ı arrow fonksiyon olarak yazmaya çalıştığımızda hata alıyoruz. Person’ın constructor olma ihtimali yok artık. Neden? Çünkü biz burada arrow fonksiyon kullanıyoruz ve arrow fonksiyonun kendisine ait this’i olmadığı için bu this’i anlamıyor. Bu sebepten dolayı arrow fonksiyonu constructor fonksiyon olarak kullanmaya çalışırsak hata alırız. Bu durumu bazen arrow fonksiyon new ile kullanılamaz şeklinde de görebiliriz. Aynı durumu ifade eder.
Arrow Fonksiyonları Bir Nesnenin Metodu Olarak Kullanmak Sıkıntılıdır
Arrow fonskiyonu bir nesnenin metodu olarak kullandığımızda beklemediğimiz sonuçlar alabiliriz.
Yukarıdaki örneği incelediğimiz zaman bir myObj nesnesinin içinde showYear’ı function declaration showYear2'yi ise arrow fonksiyon olarak tanımlıyoruz. İkisinin de yaptığı işlev aynı, ekran’a this.year’ı ve this’i yazdırmak. 11. satırda showYear metodunu çağırdığımızda ekranda 2023 ve myObj nesnesini görüyoruz bu zaten beklediğimiz bir sonuç. 12. satırda arrow fonksiyon olan showYear2'yi çağırdığımızda ise undefined alıyoruz. Çünkü arrow fonksiyonun kendine ait this’i yok ve bu this’i anlayamıyor. Arrow fonksiyon myObj’nin içinde tanımlı kendi this’i olmadığı için bir dışarıya gidiyor. Dışarıda da year diye bir değer olmadığı için undefined alıyoruz.
Evet arkadaşlar bu yazıda sizlere elimden geldiği kadar sade bir şekilde arrow fonksiyon ve this ile olan ilişkisinden bahsetmeye çalıştım. Umarım faydalı olmuştur, iyi çalışmalar.
Referanslar;
1)Arin Yazılım
2)JavaScript MDN
3)W3 Schools