Bildiğiniz gibi JavaScript’te fonksiyonlar değerdir.
Her değerin bir tipi olduğuna göre fonksiyonun tipi nedir?
JavaScript’te fonksiyon bir objedir.
Daha iyi görselleyebilmek adına fonksiyonlara “aksiyon objeleri” denebilir. Sadece çağırarak değil, obje olarak da davranabilirsiniz: özellik ekleme çıkarma, referans paslama vs.
“name” özelliği
Fonksiyon objelerinin kullanışlı özellikleri bulunmaktadır.
Örneğin, fonksiyonun ismi “name” özelliği ile alınabilir.
“name” özelliği atama o kadar akıllıdır ki, fonksiyon tanımlama ifadelerindeki ismi bile doğru alır.
Hatta atama varsayılan değer ile yapıldığında bile çalışır:
Tanımda bu özelliğe “bağlamsal isim” denir. Eğer fonksiyonda böyle bir şey yoksa, tanımlama bunu içerikten alır.
Nesne metodlarının da isimleri vardır:
Burada bir sihir yoktur. İsmin çıkarılamadığı birçok durum meydana gelebilir.
Böyle durumlarda aşağıdaki gibi boş dönerler:
Pratikte çoğu fonksiyonun ismi bulunmaktadır.
“length” özelliği
“length” adında ayrı bir özellik daha bulunmaktadır. Bu özellik fonksiyon parametrelerinin sayısını döndürür:
Gördüğünüz gibi geriye kalan parametresi ... sayılmamaktadır.
length özelliği bazen diğer fonksiyonların üzerinde çalışan fonksiyonlara bir iç bakış oluşturur.
Mesela, aşağıdaki kodda sorfonksiyonu soru parametresi alır ve belirli olmayan sayıda isleyici fonksiyonunu çağırır.
Kullanıcı cevap verdiğinde isleyici(handler) çağırılır. İki türlü işleyici gönderilebilir:
- Argümansız fonksiyon, sadece pozitif cevaplarda çağırılır.
- Argümanlı fonksiyonlar, cevap alınan her durumda çağırılır.
Mantık şu şekildedir; cevap pozitif olduğunda argüman almayan isleyici calisir, fakat evrensel isleyiciye de izin verir.
isleyici’lerin doğru çalışması için, length özelliğinden faydalanılabilir.
Bu duruma polymorphism denilmektedir. Bu argümanlara tiplerine göre farklı davranma olayıdır. Bu bizim durumumuzda length’e bağlıdır. Bu fikir JavaScript kütüphanelerinde de kullanılmaktadır.
Özelleştirilmiş özellikler
Kendi özelliğinizi eklemek de mümkündür. Örneğin aşağıda counter özelliği ile toplan çağrı sayısı tutulmaktadır:
Fonksiyona atanan selamVer.counter = 0 selamVer fonksiyonunun içerisinde counter değişkenini tanımlamaz. Diğer bir deyişle counter özelliği ile let counter birbirinden tamamen farklı şeylerdir.
Fonksiyona obje gibi davranıp özellik eklenebilir. Bu çalışmasında bir etki yaratmaz. Değişkenler fonksiyon özelliklerini kullanmaz, keza fonksiyon özellikleri de değişkenleri kullanmaz.
Fonksiyon özellikleri closure kullanılarak tekrardan yazılabilir. Örneğin yukarıdaki sayaç örneğini Closure kullanarak tekrardan yazacak olursak:
count artık fonksiyonun içerisinde bulunur, dış ortamda değil.
Closure kullanmak iyi mi kötü mü?
Eğer sayac’ın değeri dışarıdaki değişkende bulunuyorsa, dışta bulunan kod buna erişemez. Sadece içteki fonksiyon bunu modifiye edebilir. Bu da anca fonksiyona bağlıysa gerçekleşebilir:
Bundan dolayı asıl önemli olan sizin hangi şekilde kullanmak istediğiniz.
İsimlendirilmiş Fonksiyon İfadeleri ( Named Function Expression – NFE )
İsimlendirilmiş fonksiyon ifadeleri , NFE, daha önce kullandığımız Fonksiyon İfadelerinin isimlendirilmiş halidir.
Örneğin, sıradan bir Fonksiyon İfadesi incelenecek olursa:
… isimlendirilirse:
Peki buradaki mantık ne? Ayrıca bir "func" eklemenin ne anlamı var?
Tekrar etmek gerekirse, hala bir Fonksiyon İfadeniz var. Fonksiyon ifadesine "function" 'dan sonra "func" eklemek bu fonksiyonu Fonksiyon Tanımı haline getirmez çünkü hala bir atama operasyonu ile tanımlanmıştır.
Böyle bir isim eklemek hiçbir soruna neden olmaz.
Fonksiyon hala selamVer() şeklinde kullanılabilir:
func ismine ait iki tane özellik vardır:
- Bu şekilde fonksiyonun kendisine içerisinden referans vermek mümkündür.
- Fonksiyonun dışından erişilemez.
Örneğin, selamVer fonksiyonu eğer bir parametre olmadan çağırılırsa kendisini "Misafir" ile tekrardan çağırabilir.
Peki neden func kullanıyoruz? Sadece selamVer kullansak olmaz mı?
Aslında çoğu durumda olur:
Buradaki problem selamVer’in değeri değişebilir. Fonksiyon diğer bir değişkene gidebilir ardından hatalar vermeye başlar.
Bunun olmasının nedeni fonksiyonun selamVer’i dış ortamdan alıyor olmasıdır. Yerel bir selamVer bulunmadığından dıştaki değişken kullanılmaktadır. O anda da dışta bulunan selamVer null’dur.
Opsiyonel olarak konulan isim tam olarak Fonksiyon İfadesinin bu problemini çözer.
Bunu kullanarak kod şu şekilde düzeltilebilir:
Şimdi çalışır, bunun nedeni "func"'in lokal fonksiyon olmasındandır. Dışarıdan alınmaz ( dışarıdan görünmez de ). Bu şekilde yazıldığında var olan fonksiyonu referans vereceği garantidir.
Dışta bulunan kod hala selamVer veya hosGeldin değişkenlerine sahiptir. Dıştaki değişkenlere bir şey olsa bile func"iç fonksiyon ismi"'dir. Kendisini gizli biçimde çağırabilir.
“içsel isim” olarak tanımlanan özellik sadece Fonksiyon İfadeleri için geçerlidir. Fonksiyon Tanımlarında çalışmaz. Fonksiyon tanımları için “içsel” bir isim ekleme yöntemi yoktur.
Bazen güvenli bir isme ihtiyaç duyulduğunda Fonksiyon Tanımı tekrardan İsimlendirilmiş Fonksiyon İfadesi şekline getirilir.
Özet
Fonksiyonlar objedir.
Özellikleri şu şekildedir:
- name – Fonksiyon ismi. Sadece fonksiyon tanımlama da değil, atamalar ve obje özellikleri için.
- length – Fonksiyon tanımındaki argüman sayısı, geriye kalan parametreleri ( … ) sayılmaz.
Eğer fonksiyon Fonksiyon Tanımı yöntemi ile ( ana akışta olmayan ) tanımlanmışsa ve isim taşıyorsa buna İsimlendirilmiş Fonksiyon Tanımı denir. İsim içersiinde veya recursive çağrılarda kullanılabilir.
Fonksiyonlar ayrıca başka özelliklerde taşıyabilirler. Çoğu bilinen JavaScript kütüphanesi bu özelliği ziyadesiyle kullanır.
Genelde bir “ana” fonksiyon ve bu fonksiyona bağlı birçok “yardımcı” fonksiyon tanımlarlar. Örneğin jquery $ adında bir fonksiyon oluşturur. lodash fonksiyonu _ adında bir fonksiyon oluşturu. Ardıncan _.clone, _.keyBy gibi özellikleri ekler. Dökümantasyon’u inceleyebilirsiniz. Aslında, global alanda baya temiz çalışırlar. Böylece bir kütüphane bir tane global değişken vermiş olur. Bu da isimlerin birbiriyle çakışmasını engeller.
Bundan dolayı bir fonksiyon kendince bir iş yapabilir ve özellikleri vasıtasıyla başka fonksiyonalitelere de sahip olabilir.
Yorumlar