Self Invoking Anonymous Function Bölüm 2

Makalemin ikinci bölümünde Self Invoking Fonksiyon tanımlamaları için kullanılan ve Douglas Crockford tarafından önerilen popüler bir pattern’den bahsetmek istiyorum. Eğer Self Invoking Fonksiyonları hakkında bilgi sahibi değilseniz konu ile ilgili olan bir önceki makalemi okumanızı tavsiye ederim.

;(function(window, document, undefined){
  ...
})(window, document)

İlk başta bakıldığında fonksiyon bloğundan önce tanımlanan ; işaretinin ne işe yaradığını, fonksiyon’a atanan window, document, undefined gibi global değişkenlerin neden tekrardan tanımlama ihtiyacı duyulduğu düşünebilirsiniz. Düşünüldüğünde garip gelebilecek bu tanımlamaları bu kadar popüler hale getiren sebepler nelerdir? Hadi gelin beraberce inceleyelim.

self-invoking fonksiyonu tanımı öncesinde “;” kullanımının önemi

Eğer bir self-invoking fonksiyonu ile çalışacaksanız bu fonksiyonu çağırmadan önce, daha önce eklemiş olan kod bloklarının düzgün şekilde kapatılıyor olmasına dikkat etmemiz gerekmektedir. Aksi durumda fonksiyonumuz çalışmayacaktır. Bu problemin oluşmamasını garantileyebilmek için fonksiyon tanımlamamız yapılmadan hemen önce ; işareti eklenilmiştir.

var x = 42
(function () { alert("Foo")})();​ // Fonksiyonumuz çalışmayacaktır

http://jsfiddle.net/PWZu6/

var x = 42
;(function () { alert("Foo")})();​ // Fonksiyonumuz çalışacaktır

http://jsfiddle.net/sVmqz/

window ve document parametreleri

Fonksiyon içinde çağrılan local değişkenler global değişkenlere oranla biraz daha hızlı işletilirler. Bir çok script bloğumuzun içinde kullandığımız window, document global objelerinin isimlerini kısaltarak referans değişkenler oluşturmak bize birazda olsa byte kazanımı sağlayarak dosya boyutlarını düşürmemizde fayda sağlayacaktır. Ayrıca kullanılan global objeler üzerinde bir başka script tarafından yapılan değişikliklerden etkilenmediğimiz gibi bizim yaptığımız değişikliklerdende diğer scriptler etkilenmiyecektir.

// Normal
(function(window,document,undefined){ ... })(this,this.document);
// Küçültülmüş
(function(b,a,c){ ... })(this,this.document);

“undefined” parametresi

ECMAScript3 kurallarına göre undefined global objesinin değerini herhangi bir kişi tarafından rahatlıkla değiştirilebilir. Böyle bir durumda kod içinde yaptığımız undefined karşılaştırmaları doğru sonucu vermeyecek ve kod akışımızın yanlış ilerlemesini sağlıyacaktır. Bu problemin önüne geçmek için fonksiyonumuzun son parametresi olarak undefined global değişkenini eklemimiz bu problemin önüne geçicektir. Bu sorun ECMAScript5 içinde düzeltilmiştir.

undefined = true; // true
(function (undefined) {
  alert(typeof undefined); // "undefined",
})();

İlgili Makaleler

Self Invoking Anonymous Function Bölüm 1

Bu makalemde javascript içinde bence önemli bir yere sahip olan self-invoking anonymous function olarak bilinen fonksiyon tipinden ve yaygın olarak tercih edilen kullanım şekillerinden bahsediyor olucam.

Self-Invoking Anonymous Function

Self-invoking anonymous diğer fonksiyon tanımlamalarının aksine kendine ait bir ismi olmayan ve oluşturulduğu anda otomatik olarak çalışmaya başlayan fonksiyon tipidir.

// Self-Invoking Anonymous Fonksiyon Tanımı
(function(){
 // code…
})();

// Normal bir fonksiyon tanımı
function foo() {
 // code…
}

Yukarıdaki kod bloklarını dikkatli incelediğinizde ilk fonksiyonun kendine ait bir ismi olmadığı gibi alışık olduğumuzdan farklı bir syntax’a sahip olduğunu farkediceksiniz. Bildiğiniz gibi javascript içinde bir fonksiyonun çalışabilmesi için fonksiyon isminden sonra () işaretlerinin eklenmiş olması yeterlidir. Yukarıdaki örneği göz önüne aldığımızda foo isimli fonksiyonun çalışabilmesi için fonksiyon tanımı yapıldıktan sonra aşağıdaki şekilde çağırılması gerekmektedir.

function foo() {
 // code…
}
foo();

Aynı sıralama self-invoking fonksiyon tipi için geçerli değildir. Çünkü fonksiyon tanımlanması yapılır yapılmaz otomatik olarak kendiliğinden çalışmaya başlayacaktır. Aşağıdaki örnekte bunu rahatlıkla görebilirsiniz.

(function(isim, soyad) {
 alert(isim +" "+ soyad); // Volkan Altınbaş
})("Volkan", "Altınbaş");

http://jsfiddle.net/9wCx6/

Self-Invoking Fonksiyon tipini nerede kullanabilirim?

En çok tercih edilen kullanım şekli bir Scoping oluşturarak içinde yazılmış olan script tanımlarının diğer global ortamda daha önceden tanımlanmış olabilecek diğer scriptler tarafından etkilenmeyeceği bir koruma duvarı oluşturmaktır. Bir plugin yazdığınızı hayal edin. Plugininiz içinde foo() adında bir fonksiyonumuz bulunuyor. Fakat siz daha önce bu isimde bir fonksiyonun başka bir plugin tarafından kullanılıp kullanılmadığından haberdar değilsiniz. Eğer foo() isimli fonksiyonu bir self-invoking function içinde değilde gelişi güzel şekilde global bir fonksiyon olarak tanımlarsanız en son tanımlanan fonksiyon bir öncekini yok edicek ve yerini kendisi alacaktır. Bu bir fonksiyon için olabildiği gibi global olarak kullanılan bir değişken içinde aynı şekilde işleyecektir. Bu durumdan kurtulmanın en kolay ve basit yolu self-invoking fonksiyon kullanımıdır. Aşağıdaki örneklerle konunun daha iyi anlaşılacağını düşünüyorum;

// x.js
function foo() {
 alert("Volkan")
}

// y.js
function foo() {
 alert("Hakan")
}

foo(); // Hakan

http://jsfiddle.net/nHKta/

y.js dosyasının x.js dosyasından sonra sayfaya yüklendiğini hayel edin. Sonuç x.js içinde tanımlanmış olan foo() fonksiyonunun y.js içinde tanımlanan foo() fonksiyonu tarafından ezilerek yerine geçmesi sonucunun “Hakan” olması ile sonuçlanacaktır. Aynı işlemi self-invoking fonksiyonu içinde tanımlayarak denediğinizde konuyu daha net anlıyacağınızı umuyorum.

// x.js

function foo() {
 alert("Volkan")
}

// y.js
(function() {
 function foo() {
   alert("Hakan")
 }

 foo(); // Hakan

})()

foo(); // Volkan

http://jsfiddle.net/hyGa9/

İlgili Makaleler

Opera tarayıcısı üzerinde jquery & prototype kütüphanelerinin kullanımı sırasında yükseklik ve genişlik değerlerinin yanlış hesaplanması

Bir projemizde jquery 1.4.2 ve prototype 1.6.2 sürümlerini bir ara kullanmak zorunda kalabiliriz. İki kütüphaneyi bir arada kullandığımızda Opera içinde bir elemanın yükseklik yada genişlik değerini öğrenmeye çalıştığımızda almış olduğumuz değerin yanlış hesaplandığını görüceksiniz. Eğer her iki kütüphanenin daha eski sürümlerini kullanıyorsanz bu problem ile karşılaşmamanız normal.

Problemin çözümü için kütüphane dosyalarında ufak değişiklikler yapmamız gerekiyor. Problemler kütüphane sahiplerine bildirilmiş ve sanırım bir sonraki sürümlerinde çözülmüş olacaktır.

Gelelim bu problemi nasıl çözüceğimize;

Bu problemi iki farklı yöntem kullanarak çözebiliyoruz. Fakat yöntemlerden biri başka problemleride meydana getirebileceğini düşündüğümden en sağlam çözüm olacağını düşündüğüm yöntemden bahsediyor olucam.

Jquery kütüphanemizin developer’lar için hazırlanmış olan versiyonunu indiriyoruz. Daha sonra return (“scrollTo” in elem && elem.document) ? // does it walk and quack like a window? kod bloğunu bularak bu kod bloğunu return (“scrollTo” in elem && elem.document && !elem.parentNode) ? // does it walk and quack like a window? ile değiştiriyoruz. Tabiki developer sürümünün boyutu yüksek olduğundan bu sürümünü sıkıştırarak kullanmak isteyebilirsiniz. Burada yardımınıza Closure Compiler yetişiyor. Yapmanız gereken tek şey http://closure-compiler.appspot.com/home sitesine girmek ve sol taraftaki alana kod bloğunu yapıştırıp Compile düğmesine basmak. Daha sonra sağ taraftaki sonucu kopyalayarak yolumuza devam edebiliriz.

İlgili makaleler

Jquery ve Prototype javascript kütüphaneleri birlikte kullanmak için dikkat edilmesi gereken kurallar.

Günümüzdeki web projelerinde çoğu zaman birden fazla javascript kütüphanesi ile çalışmak zorunda kalabiliyoruz. Javascript kütüphanelerinden günümüzde en çok kullanılan ise Jquery ve Prototype. Bu yetenekli ikiliyi beraber kullanmak istediğimizde birşeylerin düzgün gitmediğini göreceksiniz. Sorunun kaynağı sayfa içindeki nesnelere erişmek için kullandıkları ortak $() fonksiyonundan kaynaklanmaktadır.

Sorunun çözümü ise basit. Jquery kütüphanesini Prototype kütüphanesinden önce yüklemek ve daha sonra Jquery içindeki objelere erişmek için kullandığınız $() yöntemi yerine jQuery() yöntemi kullanmak sorununuzu tamamen çözecektir. Eğer jQuery ile yazılmış ekstra pluginler kullanıyorsanız bu script dosyaları içinde bulunan $() fonksiyonunu jQuery() ile değiştemeniz gerektiğinide unutmayın. Bu işlem ilk başlarda kafanızı karıştırsada ilerde başınızı ağrıtabilecek bir çok script hatasındanda kurtaracaktır. Önerdiğim yöntem sorunun çözümü için kullanabileceğiniz en sağlam yöntemdir.

İkinci bir alternatif olan Jquery tarafından sunulan jQuery.noConflict() fonksiyonu ise çoğu zaman işe yaramamaktadır ve yukarıdaki şekilde yapılandırmanızı ayarlarsanız bu fonksiyona kesinlikle ihtiyacınızda olmayacaktır.

IE8 Hakkında Bilmeniz Gerekenler

IE8 uyumluluk modu / IE8 tarayıcısının IE7 gibi render etmesini önlemek

IE8 içinde bir düğmeye basarak sayfamızı IE7 içinde çalışır gibi davranmasını sağlayabiliyoruz. Bu düğmeye tıklandığında sayfamız bundan sonra IE7 gibi davranmaya başlayacaktır. Peki, IE7 modunda sayfamızın IE8 gibi davranma şansı varmı? Maalesef bunu yapmak mümkün değil. Eğer sayfalarımızı IE8 içinde çalışacak şekilde tasarlamış ve kesinlikle bu modda çalışmasını sağlamak istiyorsak sayfamızın içine aşağıdaki parametreyi eklemek yeterli olacaktır.

<meta http-equiv="X-UA-Compatible" content="IE=8" />

Alternatif olarak, eğer tarayıcımızın IE7 gibi davranmasını istiyorsak aşağıdaki kodu eklememiz yeterli olacaktır.

<meta http-equiv="X-UA-Compatible" content="IE=7" />

Her ne kadar bu etiketleri ekleyerek IE8’in IE7 gibi davranmasını sağlasakta bu gerçek bir IE7 gibi olmayacaktır. Bu nedenden meta etiketlerinin kullanımını önermiyorum.

IE8 CSS Hack

IE8 için kullanacağım hack yöntemi star hack yöntemini kullarak IE7 ve daha düşük versiyonları hedef alır. Fakat eski IE tarayıcıları için daha farklı hack yöntemleride kullanılabilir.

p.myclass {
color: green;
*color: red;
}

body:last-child p.myclass {
color: blue;
}

Bu hack yöntemi kullanıldığında myclass sınıfına sahip paragraflar;

sonraki postalar »