JAVASCRIPT’IN TARIHÇESI
JS de Fonksiyonun Gizemli Dünyası
JS deki fonksiyon diğer dillerde düşündüklerinizden biraz daha farklı çalışıyor ? JavaScript fonksiyon mekanizması sayesinde bu kadar güçlü, öncelikle bu konuyu anlayıp, özümsemek gerekiyor.
Benim gibi yazılıma Java ile başlayıp sonradan JS geçenler. JS’deki fonksiyon kavramını anlamaları biraz zaman alabiliyor Çünkü Java’da Class ve Metodlar üzerinden yürüyen kod geliştirme yaklaşımını JavaScript te Modül ve fonksiyonlar üzerinden devam ettiriyoruz. Ama JS fonksiyon mekaniği düşündüğümüzden çok daha güçlü ve karmaşık. Bu konuyu ne kadar iyi bilirsek JS o kadar iyi kullanabiliriz.
A. Fonksiyon İle Bağlantılı Önceki Yazılarım.
Not: Daha önceden yazılarımı takip ediyorsanız bu bölümü direk atlayabilirsiniz.
Bu yazılar fonksiyon kavramını daha iyi anlamak için temel oluşturacaktır. Daha önceden fonksiyonlar ile ilgili yazdığım yazılara bakmak isterseniz. Aşağıda bir listesini oluşturdum;
- Execution Context, Scope, Lexical Env
- this, apply/call/bind
- Fonksiyon Türleri
- Kalıtım (Inheritance)
- Default Params
- JS Rest Kavramı
- JS Spread Kavramı
- Chrome Nasıl Çalılır — JS Processing : JS Engine Objectleri nasıl ele aldığını
- Abstract Data Types
B. Mutable vs Immutable
JS 2 tip değişken vardır bir tanesi Primitives yani Number, Boolean, String vb.. diğerleride Objects yani Object, Function, vb…
Peki bu 2 tip arasındaki temel fark nedir ? Mutable ve Immutable olması. Yani Primitives Immutable’dır, Object türevi veri tipleri Mutable’dir. Ne demek bu kavramlar ?
Immutable demek kısaca değeri değiştirilemez demektir. Ama bunu const ile karıştırMayın. const bir değişkene bir değer atadıktan sonra bu değişkene bir daha atama yapamazsınız demektir. Ama örneğin bu değişkene bir array atamışşasanız bu array içerisindeki değerleri değiştirebilirsiniz. Bizim istediğimiz bir değişkene atatıdığımız bir değerin değişmemesidir.
ama bu const oluşturduğunuz bir array içeriğini değiştiremeyeceğiniz anlamına gelmez.
Peki Immutable nasıl sağlayacağız ?. Primitive değerler bunu otomatik olarak gerçekleştirir. Çünkü doğal yapıları bu şekildedir. Siz bir primitive değeri bir değişkene atadığınızda bu değer için bellekten bir yer alır ve bunun referansını bu değişken tutar. Ben bu değişkeni başka bir değişkene atadığımda ise yeni değişken bu referansı tutmaz, o referansın içerisindeki değerin bir kopyasını alarak yeni bir bellek adresine kopyalar ve bu yeni bellek adresine referans tutmayı sağlar.
Soru : Peki bu durumunun testini nasıl yapacağız?
Cevap: Elimizde a ve b değişkeni olsun. Önce a, b eşitleyeceğiz sonra bunlardan birisini değiştirip diğerinin değişip değişmediğine bakacağız.
Aşağıdaki örnekte b ile a aynı referansı tutuyor olsalardı. b değerinin değişimi a ‘nın değerini etkilerdi. Etkilemediği için bu davranışa immutable diyoruz.
Mutable demek değişkeninizin değeri değişebilir demektir. Bu değişkeni başka değişkenlere atadığınızda bu yeni değişkenlerde aynı bellek alanına referans vereceğinden değişkenlerin birisinin değişimi diğerlerinide etkileyecektir. Object türündeki JS yapıları Mutable yapıdadır.
Örneği Obj dönüştürdüğümüz anda a değişkeni b değişkenin yapmış olduğu değişiklikten etkilenmiştir. Bu yüzden bu tür yapılara Mutable yapılar diyebilir. Bu Mutable yapılardan kaçınmanın yolları mevcut
- Ama nesneden yeni bir nesne türetmek istediğinizde bu deep copy(derin kopyalama) yöntemi
- Veya daha performanslı tries veri yapısını kullanan kütüphanelerden immutable.js veya Mori kullanabilirsiniz.
C. Fonksiyon bir Object midir ?
Aynı array de olduğu gibi fonksiyon da objenin özel bir halidir. Aşağıdaki resimde user objesi ile users array altyapısında birbirinden türediklerini görebilirsiniz. Bu konuya Kalıtım (Inheritance) yazımda değinmiştim.
Peki fonksiyonlarda durum nasıl. Biz aslında fonksiyon ile bir yapı tanımlıyoruz. Bu yapı bir kod parçası aşağıdaki örnekte createUser bir obje oluşturup dönüyor. Aşağıdaki örnekte createUser fonksiyonun aslında aşağıdaki prototype üzerinde inşaa edildiğini görebilirsiniz.
- → Object __proto__
- → → f __proto__
Yani fonksiyon dediğimiz Objenin farklı yeteneklerine sahip bezenmiş bir hali.
- name: createUser
- arguments: null
- length :1
- prototype : extends → f → extends → Object
Prototype içerisine baktığımızda bind/call/apply constructor vb. fonksiyonlar bulunuyor.
Evet Fonksiyon bir Objedir. Underscore.js ve Lodash kaynak kodlarına bakarsanız. isObject fonksiyonu kontrollerini nasıl yaptığını görebilirsiniz.
D. Prototype Kendi Fonksiyonlarımı Ekleyebilir miyiz?
JS zaten en güçlü olduğu noktalardan bir taneside bu prototype kısmıdır. Extends ettiği kısımlarlarda prototype → __proto__ altından görebilirsiniz. ama hepsine .prototype ile erişebilirsiniz. Böylece istediğiniz seviyedeki
createUser.prototype.makeUpperCase = function (name) {..}
Function.prototype.makeLowerCase = function (name) { ...}
Object.prototype.makeLog=function(name){...}
E. Arrow Fonksiyon ile Normal Fonksiyon Aynı Yapıda mı ?
Not: Arrow fonksiyonlarını bilmiyorsanız daha önceden yazmış olduğum bu yazıyı okumanızı öneririm.
Bir önceki this yazımda bu konuya değinmiştim. Arrow fonksiyonlar Pure fonksiyonlar olarak matematiksel yapılar kurmak için oluşturulmuştur. Fonksiyonel Programlama yapıları için hazırlanmıştır. Bundan dolayı Constructor fonksiyonları olarak düşünülMEmelidir. constructor, apply/call/bind özellikleri yoktur. new keyword ile kullanılaMAzlar.
F. Fonksiyon Arguments Nasıl Çalışıyor.
Aşağıda toplama fonksiyonu ile ilgili yaptığım farklı farklı argüman, fonksiyona parametre geçirme çalışmalarına bakalım.
Aşağıdaki örnekte sum 2 parametre alıyor ama biz buna eksik parametre versekte çalışıyor, fazla parametre versekte çalışıyor. Yani fazla parametre geçirip geçirmeme çağıran yer ile alakalı.
Eksik parametreler için bir çözüm getirebiliriz. Default değer.
Peki hiç parametre tanımlamasak yinede çalışır mı ? Evet çalışır. Bu durumda fonksiyon içerisinde arguments içerisinde parametreleri geçirir.. Bu gizli geçen arguments ile kaç parametre geçerse geçsin generic bir toplama işlemi yaptırabiliriz.
Peki arguments → arr dönüştürme işleminden kurtulabilirmiyiz. Rest parametresi … ile bu işlemide basit bir şekilde yapabiliriz.
Javascript bize daha fazlasını yapabilmemiz için imkan’da sağlar. Parametre olarak fonksiyon geçirebilmemizi veya fonksiyon dönebilmemizi sağlar. Bu fonksiyonun aynı zamanda bir Object olabilmesi sayesinde olur.
Peki bu bize ne avantaj sağlar. Örneğin biraz önceki işlemde sadece toplama değil çarpmayı da yapabilelim dediğimizde arr.reduce fonksiyonunu tekrar yazmamızı gerek duymadan aşağıdaki şekilde kompleks yapılar kurmamızı saglar.
Bind metodu ile template fonksiyonlar oluşturup bunlarıda kullanabilirsiniz.
Özetle JS her ne kadar karmaşık olsada, Fonksiyonel Programlama yaklaşımlarını ve Fonksiyonu Parametre olup, Fonksiyon Parametre dönme yapısı üzerine kurulmuş bir çok kod geliştirme metodolojisi bulunur. Bu konuda daha detaylı bilgi almak için JS ile Fonksiyonel Programlama yazı serisini okuyabilirsiniz.
Referanslar
- Javascript: Understanding the Weird Parts
- Personal blog by Dan AbramovOkumaya Devam Et 😃
Okumaya Devam Et 😃
Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.