Object Oriented (Nesne Yönelimli) Javascript Programlama

 

Oop JavaScript

Merhaba Arkadaşlar,

1995 yılında piyasaya sürülen JavaScript, sadece html içeriğe sahip, durağan siteleri canlandırma amacı güdüyordu. Aradan geçen uzun yıllar boyunca, basit bir script dili olarak görüldüğünden dolayı, ne yazıkki yeterince değer ve itibar görmedi.

Son bir kaç yılda ise, web uygulamalarının ortaya çıkışıyla birlikte, ciddi bir değer kazanarak, popüleritesini inanılmaz oranda arttırdı. Ne varki şu an piyasada, JavaScript'in doğru yazımıyla alakalı ciddi bir sıkıntı var. Halen daha ciddi bir programlama dili gibi değil, basit bir script dili gibi görülmeye devam ediliyor. Bu yüzden C#, Java, C++, PHP vs. geliştiricilerinin aşina olduğu Object Oriented (Nesne Yönelimli), Inheritance (Kalıtım) gibi konular, ne yazıkki çoğu JavaScript geliştiricisinin ilgi alanında değil. Standart Procedurel programlama devam ediyor.

Ancak artık çok ciddi uygulamalar ortaya çıkıyor (Outlook,Gmail vs.) ve bunların yazımı, yönetimi için ciddi modülerliğe ihtiyaç duyulmaktadır. Burada da aslında OOP kavramı devreye giriyor. Peki OOP nedir?

Object Oriented Programming (Nesne Yönelimli Programlama)

Programlama akışında kullanılacak her şeyin, nesne olarak kullanıldığı, ufak modüllere bölündüğü bir kod yönetim şeklidir. En büyük avantajı kod tekrarını ortadan kaldırmasıdır.

Mesela bir kediyi modellediğimizi düşünelim. Kedi bir hayvandır. Hayvanların ortak özellikleri vardır. Her hayvan türüne, ayrı ayrı ortak özellikleri tanımlamak yerine bir seferde hayvanı tanımlayıp ortak özellikleri ekleriz. Daha sonra kedi, köpek vs. hayvan türlerini de hayvan nesnesinden türetiriz.

Oop detaylı bir konudur. Ayrıntısına bu yazıda inmeyeceğim. Bilginiz yoksa, lütfen internetten araştırma yapınız.

JavaScript OOP bir dil olsa da, basit bir şekilde inheritence vs. kavramların kullanılmasına izin vermez. Bu tarz bir yapı için biraz emek harcamak gerekmektedir.

JavaScript'te metodlarımızı function ile tanımlamaktayız.

Aşağıda,

function sample(){
alert('sample');
}

örnek bir function'u görmekteyiz. Bu function'u ise aşağıdaki gibi çağırırız.

sample();

Bu, tarayıcı ekranında alert penceresini açacaktır.

JavaScript Class

Peki server side dillerden alışkın olduğumuz class'larımızı nasıl kullanacağız?

Aşağıdaki gibi,

function Person(name,surname){
this.name=name;
this.surname=surname;
}

Person isimli bir class tanımladık ve ilk değişkenleri olan namesurname atamalarını parametre ile sağladık.

Daha sonra,

var person=new Person('Abdurrahman','Güngör');
alert(person.name);

şeklinde class'ımızdan yeni bir nesne oluşturuyoruz. Ardından da alert penceresinde person nesnesinin name değerini gösteriyoruz.

Oldukça tanıdık bir yapı, ancak ilginç olan kısım ise, metodu da, class'ı da aynı şekilde tanımladık.

İşte bu kısımda aslında tam da işlerin karıştığı kısım olarak karşımıza çıkıyor. Ne yazıkki server side dillerden sonra çokta hoş bir yapı gibi durmuyor.

Peki Person class'ımıza nasıl metod ekleyeceğiz?

function Person(name,surname){
this.name=name;
this.surname=surname;

//Yeni Ekledik
this.showVariable=function(){
alert(this.name);
}
}

var person=new Person('Abdurrahman','Güngör');
person.showVariable();

Burada ise Person class'ına showVariable adında bir metod ekledik.

Daha sonra bu metodu person nesnesi üzerinden çağırdık. Böylelikle aslında tam bir class'a sahip olmuş olduk.

 

Yalnız bir sorunumuz var. Aşağıdaki kodu inceleyelim,

function Person(name,surname){
this.name=name;
this.surname=surname;

//Yeni Ekledik
this.showVariable=function(){
alert(this.name);
}
}

var person=new Person('Abdurrahman','Güngör');
person.showVariable();

var person2=new Person('Sinan','Yakar');
person2.showVariable();

var person3=new Person('Kemal','Şahin');
person3.showVariable();

Herşey normal gibi görünüyor. Ancak burada, new Person() ile oluşturduğumuz her nesne için, içindeki tüm metodlar ayrıca ram'de yer kaplayacak şekilde oluşturuldu (burada showVariable metodu).

Bu, gözardı edilen bir sorun olsa da aslında iyi bir JavaScript yazılımcısının, bu sorunu gözardı etmemesi en doğrusu olacaktır.

JavaScript Prototype Yapısı

Prototype

Bu sorunun çözümünde ise JavaScript'in prototype yapısı ile karşılaşıyoruz. Prototype bize tanımladığımız class'lara property ve metodlar ekleyerek genişletebilme imkanı sağlamaktadır.

Mesela,

function Person(name,surname){
this.name=name;
this.surname=surname;
this.showVariable=function(){
alert(this.name);
}
}

Person.prototype.showSurname=function(){
alert(this.surname);
}

var person=new Person('Abdurrahman','Güngör');
person.showSurname();
var person2=new Person('Sinan','Yılmaz');
person2.showSurname();
var person3=new Person('Kemal','Şahin');
person3.showSurname();

burada, oluşturduğumuz Person class'ına sonradan showSurname metodunu ekleyerek yeni bir özellik eklemiş oluyoruz.

Bununla birlikte showSurname metodu artık ram'e bir kere yükleniyor ve her çağırımda, referansı üzerinden metod işletiliyor. Böylelikle ram sorununu da çözmüş oluyoruz.

Prorotype yapısıyla, metod ile birlikte property de eklemek mümkün. Ancak bu yöntemi tavsiye etmiyorum. Çünkü Person class'ından her oluşan nesnedeki propertylerden biri değiştiğinde, aynı class'tan oluşan diğer nesnelerin property'lerinin değeri de değişecektir ki, bu genelde istenen birşey değildir.

Örnek;

function Person(name,surname){
this.name=name;
this.surname=surname;
this.showVariable=function(){
alert(this.name);
}
}

Person.prototype.age=25;

var person=new Person('Abdurrahman','Güngör');
person.age=50;

JavaScript'te doğru OOP iskeleti prototype üzerine inşa edilmektedir.

Yalnız yukarıda farkedeceğiniz üzere görünüm bir class gibi olmadı, class'ı tanımladık, sonra dışarıdan ayrıca metodlarımızı prototype vasıtasıyla ekledik. Bu class'ı metodlarıyla beraber bir scope (kapsayıcı) içerisine almak için aşağıdaki yapıyı kullanabiliriz.

// Dış kapsayıcı (main scope)
var Person=(function(){

// Oluşturucu (initializer) metod
function Person(name,surname){
this.name=name;
this.surname=surname;
}

Person.prototype.showName=function(){
alert(this.name);
}

Person.prototype.showSurname=function(){
alert(this.surname);
}

//Propertylerini ve metodlarını eklediğimiz nesneyi en dıştaki Person değişkenine döndürüyoruz.
return Person;

//En sonda çağırdığımız "()" kısmı kodun otomatik olarak çalışması ve class'ın oluşturulması içindir.
})();

Biraz karışık göründüğünün farkındayım, ancak en ideal Oop JavaScript yapısı budur.

Bir kaç kez kullanırsanız, bu yapıya hızlı bir şekilde uyum sağlayacağınızdan emin olabilirsiniz.

Inheritance konusuna ise bu ders girmedim. Onu ayrı bir derste ele almayı düşünüyorum.

Bu yapıları bize çok daha rahat bir şekilde sunan CoffeeScript ve TypeScript gibi yapılar da mevcut. Bu yapılar bizim bu uğraşımızı minimuma indirerek, bazı hammaliyetleri arkada kendileri çözüyor. Bu ve benzeri yapılar JavaScript'in büyümesine büyük katkı sağlayacaktır. Bu yeni dünyaya hızlıca uyum sağlamamız, zaruri görünüyor.

Hepinize kolaylıklar diliyorum.