Bu makalemizde, JavaScript geliştiricilerin sevgilisi ve İsviçre çakısı olan Underscore kütüphanesini inceleyeceğiz.

Underscore'u övmek için pek çok şey söyleyebilirim. Örneğin bu arkadaş ile tanışanların bundan sonraki mesleki kariyerinde yazacağı for sayısı, şimdiye kadar yazdıklarının toplamından az olacaktır iddiasında bulunabilirim. Ya da bir kere Underscore'a alışanlar, bir önceki makalemde anlattığım Linq kütüphanesine belki de hiç ihtiyaç duymayacaktır da diyebilirim. Ama bunların tamamı benim subjektif yorumlarımdan ibaret olur. Bunun yerine daha elle tutulur bir referans ile işe başlayalım.





Yukarıdaki görüntü, ben bu makaleyi yazarken Node.JS'in paket kütüphanesi olan NPM'de bulunan paketlerin en çok kullandığı/bağımlı olduğu kütüphanelerin listesini gösteriyor. Underscore'un ezici üstünlüğü açıkça göze çarpıyor. Elbette Underscore'u sadece sunucu tarafında kullanmak zorunda değiliz, aynı fonksiyonalite istemci tarafında da kullanımımıza sunuluyor.

Underscore an itibariyle, pek çok derde deva 80 adet fonksiyon ile birlikte geliyor. Ben burada en çok kullanılan 55 tanesine yer vereceğim. Tüm fonksiyonlar hakkında referansa ihtiyacı olanlar buradan gerekli bilgilere ulaşabilirler.

Not  : Bu notu, makaleyi tamamlayıp imla denetimi için tekrar okurken yazıyorum. Normalde yukarıda 55 yazan yerde 10-15 yazıyordu. Ancak yazım sırasında şu da kullanılıyor, bu da kullanılıyor derken fark ettim ki, Underscore'daki fonksiyonların çoğu zaten sık kullanılıyor. Bu yüzden makale biraz uzamış oldu, idare ediver.

Fonksiyonlar Collections, Arrays, Functions, Objects, Utility ve Chaining olmak üzere 6 başlık altında toplanmış bulunuyor. Bunlardan Collections ve Array başlığı altında bulunanlar, Linq benzeri ancak daha güçlü ve esnek fonksiyonaliteleri sunarken, diğer kategoridekiler JQuery benzeri sık kullanılan işlemleri tek satır kod yazarak gerçekleştirmemize imkan sağlayan kolaylıkları ayağımıza getiriyor.

Elbette kullanmaya başlamadan önce ilk olarak kütüphanenin güncel versiyonunu resmi sitesinden indirmemiz ve sayfamıza eklememiz gerekiyor. Ben bu makaleyi yazarken son versiyon 1.6.0 olarak gözüküyordu.


Buradaki "Production Version" dosyasını "underscore-1.6.0.min.js" olarak isimlendirip kullanmak üzere masaüstüne koyalım. Ardından hemen yanına aşağıdaki kodlarla HTML belgemizi hazırlayalım (program.js dosyasının içeriğini, aşağıdaki başlıklarda ayrı ayrı veriyorum).


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1254" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="underscore-1.6.0.min.js"></script>
<script src="program.js"></script>
</head>
<body>
</body>
</html>

times, each 

İşin aslı, aşağıda göreceğimiz fonksiyonlar sebebiyle yazacağımız döngülerin sayısı oldukça azalacak ancak yine de döngü yazmamız gereken durumlarda, for ve foreach yerine times ve each fonksiyonlarını kullanarak daha kompakt bir kod elde edebiliriz.

"use strict";

$(document).ready(function () {

    _.times(3, function (i) {
        $("body").append(i + "<br>");
    });

    $("body").append("<br>");


    var data = [
        {name: "Ali", age: 45},
        {name: "Veli", age: 25}
    ];

    _.each(data, function (item) {
        $("body").append(item.name + " " + item.age + "<br>");
    })
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



Not  : JQuery'nin "$" işareti gibi, Underscore'un da "_" işareti vardır ve tüm fonksiyonlara bunun üzerinden erişilir.

Örneğimizdeki "times" fonksiyonuna geçilen ilk parametre, döngünün dönüş adedini gösteriyor. Buradaki sayı adedince fonksiyona ikinci parametre olarak geçilen fonksiyon çağırılıyor ve parametre olarak da döngünün indeks değeri geçiliyor. Bildiğimiz for döngüsünün daha kompakt versiyonu.

"each" fonksiyonunda ise ilk parametre, içerisinde dönülecek diziyi belirtiyor. Dizideki eleman adedince fonksiyona ikinci parametre olarak geçilen fonksiyon çağırılıyor ve parametre olarak da dizinin sıradaki elemanı geçiliyor. Bu da bildiğimiz foreach döngüsünün daha kompakt versiyonu.


where, findWhere

Bu ikili, en basit anlamda diziden belirtilen kriterlere uygun kayıt (findWhere) veya kayıtları (where) çekmemize imkan sağlıyor.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var list = _.where(data, { gender: "Erkek", age: 45 });

    $("body").append(JSON.stringify(list));

    $("body").append("<br>");
    $("body").append("<br>");

    var user = _.findWhere(data, {name: "Veli"});

    $("body").append(JSON.stringify(user));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



Burada fonksiyonlarımıza geçilen ilk parametre, üzerinde aramanın gerçekleştirileceği diziyi, ikinci parametre de arama ifadesini gösteriyor. Aynı anda birden fazla kritere göre arama yapmak için, kriterler arasına virgül koyuyoruz. Bu iki fonksiyon, bir anlamda Linq'deki Where ile ToList/FirstOrDefault fonksiyonlarına benziyor.


filter, find

Her ne kadar az önce kullandığımız iki fonksiyon kolay ve pratik olsa da, Underscore'un gerçek gücünü anlayacağımız en temel iki fonksiyona gelmiş bulunuyoruz. Bu ikili yine diziden belirtilen kriterlere uygun kayıt (find) veya kayıtları (filter) çekmemize imkan sağlıyor. Ancak çok çok daha güçlü ve esnek bir şekilde.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var list = _.filter(data, function (item) {
        return item.gender == "Erkek" && item.age == 45;
    });

    $("body").append(JSON.stringify(list));

    $("body").append("<br>");
    $("body").append("<br>");

    var user = _.find(data, function (item) {
        return item.name == "Veli";
    });

    $("body").append(JSON.stringify(user));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



Burada fonksiyonlarımıza geçilen ilk parametre, yine üzerinde aramanın gerçekleştirileceği diziyi gösteriyor. Dizinin her bir elemanı için ikinci parametre olarak geçilen fonksiyon çağırılıyor ve dizinin ilgili elemanı fonksiyona parametre olarak geçiliyor. Eğer fonksiyon içerisinden "true" değer dönersek, ilgili elemanı sonuca eklemiş, "false" dönersek eklememiş oluyoruz. Bu yüzden, az önceki örneğimiz ile aynı mantıkta çalışacak tek satırlık bir boolean ifade yazıyoruz.

Peki bu ikiliyi bu kadar güçlü yapan nedir? Üstelik yazımı bir önceki ikiliye göre daha karmaşık gözüküyor. Hiç yoktan bir de fonksiyon yazmak zorunda kaldık.

Aslında işin sırrı burada. İkinci parametre olarak yazdığımız fonksiyon, standart bir JavaScript fonksiyonu. Biz burada tek satırlık bir koşul ekledik ama isteseydik gidip dışarıdaki bir Web Service'e bağlanıp bir şeyler de sorabilirdik, ya da veritabanından sorgu da çekebilirdik. Düşün ki, TC kimlik numarası geçerli olup veritabanında bulunmayan kişilerin listesini filtrelemek isteseydik, bu fonksiyon içerisinden MERNİS'e bağlanıp kimlik numarası kontrolü yapabilir, ardından da ilgili kişinin veritabanında bulunup bulunmadığına bakarak, ona uygun bir cevap dönebilirdik. Buradaki fantezilerde pratik olarak bir sınır yok. Bunun Linq karşılığını yazmak isteyen var mı?


without, reject 

Bu ikili de, verilen koşula uymayan kayıtları filtreliyor.

"use strict";

$(document).ready(function () {

    var data1 = ["Ali", "Veli", "Ahmet", "Mehmet"];

    var list1 = _.without(data1, "Ali", "Mehmet");

    $("body").append(JSON.stringify(list1));

    $("body").append("<br>");
    $("body").append("<br>");

    var data2 = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" }
    ];

    var list2 = _.reject(data2, function (item) {
        return item.name == "Ali" || item.name == "Mehmet";
    });

    $("body").append(JSON.stringify(list2));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



"without" fonksiyonu basitçe, verilen dizideki belirtilen elemanları eleyip geri kalanı dönüyor. "reject" fonksiyonu ise bir üstteki "filter" gibi filtreleme fonksiyonu yazarak daha kompleks işlemler gerçekleştirmemize imkan sağlıyor.


mappluck, pick, omit

Bu dördü, özellikle de "map" fonksiyonu bulunmaz nimet. Bir objeyi farklı tipte bir objeye çevirmemize imkan sağlıyor.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var list1 = _.map(data, function (item) {
        return { userId: item.id, username: item.name };
    });

    $("body").append(JSON.stringify(list1));

    $("body").append("<br>");
    $("body").append("<br>");


    var list2 = _.pluck(data, "name");

    $("body").append(JSON.stringify(list2));

    $("body").append("<br>");
    $("body").append("<br>");


    var list3 = _.pick(data[0], "name", "gender");

    $("body").append(JSON.stringify(list3));

    $("body").append("<br>");
    $("body").append("<br>");


    var list4 = _.omit(data[0], "age");

    $("body").append(JSON.stringify(list4));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



"map" fonksiyonuna ilk parametre olarak geçtiğimiz dizinin her bir elemanı, ikinci parametre olarak geçtiğimiz fonksiyona parametre olarak geçiliyor. Ardından bu fonksiyonda döndüğümüz nesne şeklinde bir dizi oluşturuluyor. Böylece bir diziyi, ihtiyacımıza uygun yapıdaki başka bir diziye çevirebiliyoruz.

"pluck" fonksiyonu, "map" fonksiyonunun özelleştirilmiş bir versiyonu. Bir diziden, sadece belirtilen elemanları alarak bir dizi üretiyor.

"pick" ve "omit" ise dizi yerine direk nesne üzerinde çalışıyor. "pick" ile nesnenin sadece belirtilen elemanlarını alarak yeni bir nesne üretiyoruz. "omit" ile ise tam ters şekilde, belirtilen elemanların haricindeki elemanları alarak yeni bir nesne üretiyoruz.


reduce

Oldukça ilginç uygulamaları olan "reduce" fonksiyonu ile özet olarak, dizinin elemanları arasında gezinerek belirtilen hesaplamaları yaptırıyor ve geriye bir sonuç dönüyoruz.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var totalAge = _.reduce(data, function (memo, item) {

        memo = memo.age || memo;

        return memo + item.age;
    });

    $("body").append(totalAge);
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



"reduce" fonksiyonu, işleme tabii olacak dizi ve hesaplamayı yapacak fonksiyon şeklinde iki farklı parametre alıyor. Fonksiyonumuzun her çağrımında da iki ayrı parametre geçiliyor. Bunlardan ilki (memo), eğer fonksiyonun ilk çağırımı ise dizinin ilk elemanı, takip eden çağırımları ise önceki fonksiyondan dönen değeri gösteriyor. İkinci parametre ise (item), dizinin sıradaki elemanını içeriyor.

Reduce işleminin ihtiyaca göre pek çok değişik kullanım alanı var. Biz burada örnek olarak, dizide bulunan herkesin yaşlarının toplamını elde ettik.


everysome

Bu ikili, verilen dizideki tüm elemanların (every) veya en az bir elemanın (some) belirtilen kritere uyup uymamasına göre true veya false değer döndürüyor.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var isEveryRecordsErkek = _.every(data, function (item) {
        return item.gender == "Erkek";
    });

    $("body").append(isEveryRecordsErkek.toString());

    $("body").append("<br>");
    $("body").append("<br>");


    var isSomeRecordsErkek = _.some(data, function (item) {
        return item.gender == "Erkek";
    });

    $("body").append(isSomeRecordsErkek.toString());
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



Örneğimizdeki ilk denememiz, dizinin tüm elemanlarının "gender" özelliğinin "Erkek" olup olmadığının kontrolüydü. İkinci denemede ise, en az bir adet "Erkek" olup olmadığını kontrol ettik.


minmax

Muhtemelen fazla bir şey söylemeye gerek yoktur, direk örneğe geçelim.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var minAgedItem = _.min(data, function (item) {
        return item.age;
    });

    $("body").append(JSON.stringify(minAgedItem));

    $("body").append("<br>");
    $("body").append("<br>");


    var maxAgedItem = _.max(data, function (item) {
        return item.age;
    });

    $("body").append(JSON.stringify(maxAgedItem));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



Her iki fonksiyonda da, iç fonksiyondan dönülen değerlerden en küçük ve en büyük değerlere sahip olan nesne seçilerek ekrana yazdırılıyor.


shuffle
sample

İşte ilginç bir ikili. "shuffle", adından da anlaşılacağı üzere, verilen dizinin elemanlarının yerlerini rastgele olarak karıştırıyor. "sample" ise, dizinin elemanlarından rastgele birisini (veya belirtilen adet kadarını) seçerek döndürüyor.

"use strict";

$(document).ready(function () {

    var data = [1, 2, 3, 4 , 5, 6];

    var shuffledList = _.shuffle(data);

    $("body").append(JSON.stringify(shuffledList));

    $("body").append("<br>");
    $("body").append("<br>");


    var randomItems = _.sample(data, 2);

    $("body").append(JSON.stringify(randomItems));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor (Sayılar farklı olacaktır).



Muhtemelen daha fazla açıklamaya gerek yoktur.


random

Hazır rastgele işlem yapan fonksiyonlardan bahsetmişken, "random" fonksiyonuna da değinmezsek olmaz. Bu arkadaşımız, belirtilen alt ve üst sınırlar içerisinde rastgele bir tam sayı üretiyor.

"use strict";

$(document).ready(function () {

    var randomNumber = _.random(1, 100);

    $("body").append(randomNumber);
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor (Sayı farklı olacaktır).



Boşuna İsviçre çakısı demiyorum :)


firstlast, initial, rest

Bu dörtlü, dizinin elemanlarından belirtilen bir kısmını döndürüyor. Örnek üzerinde görelim.

"use strict";

$(document).ready(function () {

    var data = [
        { id: 1, name: "Ali", age: 45, gender: "Erkek" },
        { id: 2, name: "Veli", age: 25, gender: "Erkek" },
        { id: 3, name: "Ahmet", age: 45, gender: "Erkek" },
        { id: 4, name: "Mehmet", age: 20, gender: "Erkek" },
        { id: 5, name: "Ayse", age: 40, gender: "Kadin" },
        { id: 6, name: "Fatma", age: 30, gender: "Kadin" }
    ];

    var list1 = _.first(data, 2);

    $("body").append(JSON.stringify(list1));

    $("body").append("<br>");
    $("body").append("<br>");


    var list2 = _.last(data, 2);

    $("body").append(JSON.stringify(list2));

    $("body").append("<br>");
    $("body").append("<br>");


    var list3 = _.initial(data, 4);

    $("body").append(JSON.stringify(list3));

    $("body").append("<br>");
    $("body").append("<br>");


    var list4 = _.rest(data, 4);

    $("body").append(JSON.stringify(list4));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



"first" fonksiyonu, dizinin başından belirtilen miktarda elemanı döner. "last" fonksiyonu da tam tersi, dizinin sonundan belirtilen miktarda elemanı döner. "initial" fonksiyonu, dizinin sonundan belirtilen miktarca elemanı atar ve geri kalanı döner. "rest" fonksiyonu ise dizinin başından belirtilen miktarca elemanı atar ve geri kalanı döner.


unionintersection, difference

İşte çok işe yarayacak bir üçlü daha. Yine örnek üzerinde görelim.

"use strict";

$(document).ready(function () {

    var data1 = [1, 2, 3, 4],
        data2 = [2, 4, 6],
        data3 = [4, 5, 6, 7];

    var list1 = _.union(data1, data2, data3);

    $("body").append(JSON.stringify(list1));

    $("body").append("<br>");
    $("body").append("<br>");


    var list2 = _.intersection(data1, data2, data3);

    $("body").append(JSON.stringify(list2));

    $("body").append("<br>");
    $("body").append("<br>");


    var list3 = _.difference(data1, data2, data3);

    $("body").append(JSON.stringify(list3));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



"union" fonksiyonu, verilen dizilerin birleşimini alır. "intersection" ise tüm dizilerin kesişimini alır. Son olarak "difference" fonksiyonu da, ilk dizinin diğer dizilerden farkını döndürür.


uniq

SQL'deki Distinct fonksiyonun benzeri olan "uniq" fonksiyonu, dizide tekrarlanan elemanları siler.

"use strict";

$(document).ready(function () {

    var data = [1, 2, 3, 4, 2 , 4 , 1, 5, 6, 4];

    var distinctlist = _.unique(data);

    $("body").append(JSON.stringify(distinctlist));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




range

"range" fonksiyonu, belirtilen değerden başlayarak, belirtilen değere kadar, belirtilen adımda artan sayılardan oluşan bir dizi oluşturur.

"use strict";

$(document).ready(function () {

    var list = _.range(5, 20, 2);

    $("body").append(JSON.stringify(list));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




debounce

Bu arkadaş, doğru kullanıldığında çok faydalı olabiliyor. Bununla normal bir fonksiyonun yerini temsil edecek bir  fonksiyon tanımlarız. Tanımlama sırasında da milisaniye cinsinden bir süre veririz. Tanımladığımız bu temsili fonksiyon, belirtilen süre içerisinde en fazla 1 kez çağırılabilir, süre dolana kadar takip eden diğer çağırımlar işletilmez.

Nerede mi kullanılır? Örneğin çift tıklama sendromu müptelası kullanıcılarımızın ekrandaki butonlara mükerrer basmaları sırasında, ilk basıştan itibaren 0,5 saniye boyunca tıklamaların geçersiz hale getirilmesi bir örnek olabilir mi?

"use strict";

$(document).ready(function () {

    var writeTest = function () {
        $("body").append("test");
    };

    var writeTestFn = _.debounce(writeTest, 1000, true);

    writeTestFn();
    writeTestFn();
    writeTestFn();
    writeTestFn();
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




keys, values, pairs, invert

İşte ilginç bir dörtlü daha. key-value tarzında değerler içeren bir nesnemiz olduğunu varsayalım. "keys" fonksiyonu, bu dizideki tüm key değerlerini, "values" fonksiyonu da, dizideki tüm value değerlerini döndürür. "pairs" fonksiyonu, key ve value değerlerini dizi halinde gruplar. "invert" fonksiyonu da key ile value değerlerinin yerlerini değiştirir.

"use strict";

$(document).ready(function () {

    var data = {one: 1, two: 2, three: 3};

    var keys = _.keys(data);

    $("body").append(JSON.stringify(keys));

    $("body").append("<br>");
    $("body").append("<br>");


    var values = _.values(data);

    $("body").append(JSON.stringify(values));

    $("body").append("<br>");
    $("body").append("<br>");


    var pairs = _.pairs(data);

    $("body").append(JSON.stringify(pairs));

    $("body").append("<br>");
    $("body").append("<br>");


    var inverted = _.invert(data);

    $("body").append(JSON.stringify(inverted));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




functions

Bu fonksiyon ile, belirtilen nesne altında bulunan tüm fonksiyonların listesini alabiliriz. Örneğin Underscore kütüphanesindeki tüm fonksiyonların listesini bir görelim bakalım.

"use strict";

$(document).ready(function () {

    var functions = _.functions(_);

    $("body").append(JSON.stringify(functions));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




extend, defaults

İşte çok işe yarayacak bir ikili daha. Bu ikisine hemen hemen object mapper diyebiliriz. "extend" fonksiyonu, verilen bir nesnedeki özellikleri, ikinci nesneye ekler. İkinci nesnede bulunan özellikler olduğu gibi korunurken, kesişen özelliklerin değerleri üzerine yazılır. İşte burada da "extend" ile "defaults" arasındaki fark ortaya çıkar. "extend" değerlerin üzerine yazarken, "defaults" mevcut değerleri korur ve sadece olmayan özellikleri nesneye ekler.

"use strict";

$(document).ready(function () {

    var data1 = { id: 1, name: "Ali"};

    var data2 = { name: "Veli", age: 45, gender: "Erkek" };

    var data3 = { id: 1, name: "Ali"};

    _.extend(data1, data2);

    $("body").append(JSON.stringify(data1));

    $("body").append("<br>");
    $("body").append("<br>");


    _.defaults(data3, data2);

    $("body").append(JSON.stringify(data3));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




clone

Nesne kopyalama, pek çok kez ihtiyaç duyulan bir işlemdir. Referans tipindeki değerler "=" operatörü ile kopyalanamazlar, bunların referans gösterdikleri değerler aynıdır ve biri değiştiği takdirde diğeri de değişir. Birbirinden tamamen kopuk ama aynı özelliklere sahip iki nesne elde etmek istersek, orijinal nesneyi kopyalamamız gerekir. Bunun için internette JSON.parse(JSON.stringify(obj)) gibi ifadeler görmüş olabilirsin. İşte "clone" fonksiyonu bu işi kolayca gerçekleştirmemize imkan sağlar.

"use strict";

$(document).ready(function () {

    var data = { id: 1, name: "Ali"};

    var clonedData = _.clone(data);

    $("body").append(JSON.stringify(clonedData));
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




isEqual, isEmpty, isElement, isArray, isObject, isArguments, isFunction, isString, isNumber, isFinite, isBoolean, isDate, isRegExp, isNaN, isNull, isUndefined

Bu arkadaşlar, adlarından da anlaşılacağı üzere, verilen değerin belirli kriterlere uyup uymadığını kontrol ederek true veya false değer dönerler.

"use strict";

$(document).ready(function () {

    var isEqual = _.isEqual({name: "Ali", age: 45}, {name: "Ali", age: 45});
    var isEmpty = _.isEmpty({});
    var isElement = _.isElement($("body")[0]);
    var isArray = _.isArray([1, 2]);
    var isObject = _.isObject({name: "Ali", age: 45});
    var isArguments = _.isArguments({name: "Ali", age: 45});
    var isFunction = _.isFunction(function () { alert("test"); });
    var isString = _.isString("Ali");
    var isNumber = _.isNumber(45);
    var isFinite = _.isFinite(Infinity);
    var isBoolean = _.isBoolean(1 == 2);
    var isDate = _.isDate(new Date());
    var isRegExp = _.isRegExp(/test/);
    var isNaN = _.isNaN(undefined);
    var isNull = _.isNull(null);
    var isUndefined = _.isUndefined(undefined);

    $("body").append(isEqual.toString() + "<br>");
    $("body").append(isEmpty.toString() + "<br>");
    $("body").append(isElement.toString() + "<br>");
    $("body").append(isArray.toString() + "<br>");
    $("body").append(isObject.toString() + "<br>");
    $("body").append(isArguments.toString() + "<br>");
    $("body").append(isFunction.toString() + "<br>");
    $("body").append(isString.toString() + "<br>");
    $("body").append(isNumber.toString() + "<br>");
    $("body").append(isFinite.toString() + "<br>");
    $("body").append(isBoolean.toString() + "<br>");
    $("body").append(isDate.toString() + "<br>");
    $("body").append(isRegExp.toString() + "<br>");
    $("body").append(isNaN.toString() + "<br>");
    $("body").append(isNull.toString() + "<br>");
    $("body").append(isUndefined.toString() + "<br>");
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.




mixin

Bu makaledeki son fonksiyonumuza da gelmiş bulunuyoruz çok şükür. Eğer ki Underscore içerisindeki fonksiyonlar bize yetmez de, kendimize göre yenilerini eklemek istersek, "mixin" fonksiyonu ile amacımıza ulaşabiliriz. Bir kez eklediğimiz bir fonksiyona ihtiyaç duyduğumuzda da, "_" üzerinden rahatlıkla ulaşabiliriz.

"use strict";

$(document).ready(function () {

    _.mixin({
        pascalCase: function (text) {
            return text.charAt(0).toUpperCase() + text.substring(1).toLowerCase();
        }
    });

    var test = _.pascalCase("deneme");

    $("body").append(test);
});

Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.



Örneğimizde, Underscore'da bulunmayan Pascal Case çevirme fonksiyonunu eklemiş ve sonradan "_" üzerinden çağırmış olduk.



Yine geldik uzun bir makalenin sonuna. Artık nasıl yapacaksak, öğrendiklerimizi özetlemeye çalışalım bakalım.
  • Underscore.JS candır.
  • JQuery'deki "$" işareti gibi, Underscore da "_" işaretini kullanır.
  • Underscore sayesinde, JQuery'de olduğu gibi sık gerçekleştirdiğimiz işlemleri tek bir satır kod yazarak aradan çıkartabiliriz.
  • Bu kütüphane İsviçre çakısına benzer. Linq benzeri fonksiyonların yanında, nesneler üzerinde modifikasyon yapmaya, değerleri karşılaştırmaya, döngüler yazmaya ve hatta rastgele sayı üretmeye yarayan fonksiyonlar içerir.
  • Underscore'un mevcut fonksiyonları yetmediği durumda, "mixin" fonksiyonu sayesinde kütüphaneye kendi ihtiyacımız olan fonksiyonları da ekleyebilir ve projemiz boyunca "_" işareti üzerinden bu fonksiyonlara erişebiliriz.


Yorum Gönder

  1. Böyle bir makele için ne kadar çok teşekür edilse azdır.

    YanıtlaSil
  2. Hocam döktürmüşsün yine eline sağlık

    YanıtlaSil
  3. Ellerinize sağlık

    YanıtlaSil

 
Top