Ok Fonksiyonları

Kalın ok (çünkü -> ince ok (thin arrow), => ise kalın oktur (fat arrow)) veya lambda fonksiyonu (diğer dillerde geçtiği şekliyle) olarak isimlendirilir. ()=>something, kalın ok fonksiyonunun çokça kullanılan bir özelliğidir. Kalın ok fonksiyonunun kullanılmasının nedenleri:

  1. function yazmanıza gerek olmaz.
  2. Anlam olarak this sözcüğünü içerir.
  3. Anlam olarak arguments sözcüğünü içerir.

İşlevsel (fonksiyonel) olduğunu iddia eden bir dil olarak JavaScript'te fazlasıyla function yazma eğiliminde olursunuz. Kalın ok size kolay bir şekilde fonksiyon yaratmanızı sağlar.

var inc = (x)=>x+1;

this genel olarak Javascript'te sıkıntılı bir konudur. Bilge bir adam der ki, "this, çok kolay bir biçimde anlamını yitirdiği için Javascript'ten nefret ettim." Kalın ok bu durumu this'in anlamını etrafındaki içerikle yansıtarak düzeltti. Şu saf Javascript sınıfına bakarsak:

function Person(age) {
    this.age = age;
    this.growOld = function() {
        this.age++;
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 1, ama 2 olmalıydı

Eğer bu kodu tarayıcıda çalıştırırsanız, fonksiyon içindeki this, window'u işaret eder çünkü growOld fonksiyonunu window yürütecektir. Bunu düzeltmek için ok fonksiyonu kullanın:

function Person(age) {
    this.age = age;
    this.growOld = () => {
        this.age++;
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 2

Bunun işe yaramasının sebebi, ok fonksiyonunun this referansını fonksiyon gövdesinin dışından almasıdır. Buna eşdeğer Javascript kodu (TypeScript kullanmadan da yazabilirsiniz) ise aşağıdaki gibidir:

function Person(age) {
    this.age = age;
    var _this = this;  // this'i referans alır
    this.growOld = function() {
        _this.age++;   // referans alınan this kullanılır
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 2

Ayrıca artık TypeScript kullandığınız için, daha güzel bir sözdizimi ile ok fonksiyonlarını sınıflar ile kullanabilirsiniz:

class Person {
    constructor(public age:number) {}
    growOld = () => {
        this.age++;
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 2

İpucu: Ok Fonksiyonu Gereksinimi

Kısa ve öz sözdiziminin dışında, sadece fonksiyonunuz başkası tarafından çağrılacaksa, kalın ok kullanmanız gereklidir. Örneğin:

var growOld = person.growOld;
// Ve sonra başkası çağırdığında:
growOld();

Eğer fonksiyonu kendiniz çağıracaksanız, örneğin;

person.growOld();

İşte o zaman this doğru bir içeriği çağırmış olur (person örneğindeki gibi).

İpucu: Tehlikeli Ok Fonksiyonu Kullanımı

Aslında this'i ilgili içeriği çağırmak için istiyorsanız, ok fonksiyonu kullanmamalısınız. jquery, underscore, mocha gibi geri çağırımlar (callback) kullanan kütüphaneler bu duruma örnektir. Eğer dökümanında fonksiyonlarda this kullanımından bahsediyorsa, o zaman kalın ok yerine muhtemelen function kullanmanız gerekiyor. Aynı şekilde eğer arguments kullanmayı düşünüyorsanız da, kalın ok fonksiyonu kullanmamalısınız.

İpucu: Ok fonksiyonları ve this kullanan kütüphaneler

Birçok kütüphane bunu yapmaktadır. Örneğin, jQuery yineleyicileri (iterable) (bir örneği http://api.jquery.com/jquery.each/) o an yinelenmekte olan nesneye this'i iletecektir. Bu durumda, this'i ve çevreleyen içeriğini ileten bir kütüphaneye erişmek istiyorsanız, benzeri bir geçici değişken kullanın:

let _self = this;
something.each(function() {
    console.log(_self); // sözcük anlamı olarak kapsamın değeri
    console.log(this); // kütüphanenin ilettiği değer
});

İpucu: Ok fonksiyonları ve kalıtım

Diyelim ki ok fonksiyonu ile yazılıp this ile devam eden, bir sınıfa ait bir metodunuz var. Sadece tek bir this olduğundan, bu tip fonksiyonlar super'i (super sadece prototip üyelerinde çalışır) çağıramazlar. Alt sınıf metodun üzerinden geçmeden önce, metodun kopyasını yaratarak bunun üstesinden gelebilirsiniz.

class Adder {
    constructor(public a: number) {}
    // Bu fonksiyon şu an çağrılabilmeye uygun
    add = (b: string): string => {
        return this.a + b;
    }
}

class ExtendedAdder extends Adder {
    // Kendi metodundan önce üst sınıfınkinin bir kopyasını yarat
    private superAdd = this.add;
    // Şimdi onun üzerinden geçen kendi metodunu yarat
    add = (b: string): string => {
        return this.superAdd(b);
    }
}

results matching ""

    No results matching ""