[ Web Proxy ]
URL:
Viewing: https://tr.javascript.info/bind [Back]  [Original]

Fonksiyon balama
TR

Bu ak-kaynakl projenin tm dnyada kullanlabilir olmasn istiyoruz.

Kendi dilinizde eviriye yardm edebilirsiniz!

    Javascript.info'da ara:
    Eitimde ara:
    Light themeDark theme
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Obje metodlar ile setTimeout kullanldnda veya obje metodlar iletilirken, thisin kaybolmas bilinen bir problemdir.

    Aniden, this kaybolur. Bu problem balang seviyesi gelitiriciler iin ok tipiktir, bazen deneyimli gelitiriciler de bu hataya derler.

    "this"i kaybetme

    JavaScriptte this in ne kadar kolay bir ekilde kaybolduunu zaten biliyorsunuz. Eer bir metod objeden farkl bir yere iletilirse this kaybolur.

    Bu setTimeout ile nasl olur bakalm:

    let user = {
      firstName: "John",
      sayHi() {
        alert(`Hello, ${this.firstName}!`);
      }
    };
    
    setTimeout(user.sayHi, 1000); // Hello, undefined!

    Grdnz gibi, kt "John"u gstermedi bunun yerine undefined dnd!

    Bunun nedeni setTimeoutun user.sayHi fonksiyonunun objeden ayr olmasdr. Son satr u ekilde yazlabilir:

    let f = user.sayHi;
    setTimeout(f, 1000); // kullanc kayna kayboldu

    Taraycda setTimeout kullanm biraz zeldir: this=window olarak ayarlanr. ( Node.JS iin this timer objesi olur, fakat burada pek de nemli deil.) yleyse this.firstName bu deeri window.firstNameden almaya alr, fakat byle bir ey yok. Buna benzer durumlarda siz de greceksiniz this genelde undefined olur.

    Aslnda yapmak istediimiz ok basit obje metodunu arlan yere ( ) iletmek istiyoruz ( burada zamanlaycdr). Bunun doru kaynakta arldna nasl emin olunabilir?

    zm 1: saklayc

    En basit zm bir saklayc ( wrapper ) fonksiyonu kullanmaktr:

    let user = {
      firstName: "John",
      sayHi() {
        alert(`Hello, ${this.firstName}!`);
      }
    };
    
    setTimeout(function() {
      user.sayHi(); // Hello, John!
    }, 1000);

    almasnn nedeni user d szck ortamndan almasdr, sonrasnda metodu normal bir ekilde altrr.

    Ayns, fakat biraz daha ksa hali:

    setTimeout(() => user.sayHi(), 1000); // Hello, John!

    Fena deil, fakat kod yapsal olarak biraz sorunlu grnyor.

    setTimeout almadan nce ( 1 sn ara ile alyor ) user deeri deiirse? Sonra aniden yanl objeyi aracaktr.

    let user = {
      firstName: "John",
      sayHi() {
        alert(`Hello, ${this.firstName}!`);
      }
    };
    
    setTimeout(() => user.sayHi(), 1000);
    
    // ...kullancnn deeri 1 saniye iinde deiir
    user = { sayHi() { alert("Another user in setTimeout!"); } };
    
    //SetTimeout'da baka bir kullanc!

    Bir sonraki zm ie byle bir eyin olmasn engeller.

    zm 2: balama

    Fonksiyonlar bind varsaylan fonksiyonu salarlar. Bu fonksiyon thisin sabitlenmesini olanak verir.

    Basite yazm u ekildedir:

    // daha karmak yazmlarna ileride geleceiz.
    let boundFunc = func.bind(kaynak);

    func.bind(kaynak)'n sonucu zel bir fonksiyon benzeri "egzotik obje"dir. Fonksiyon gibi arlabilir ve saydam bir ekilde ary funca this=kaynak olacak ekilde iletir.

    Dier bir deyile boundFunc aslnda sabit thise sahip funcdur.

    rnein burada funcUser ary func fonksiyonuna this=user olacak ekilde iletir.

    let user = {
      firstName: "John"
    };
    
    function func() {
      alert(this.firstName);
    }
    
    let funcUser = func.bind(user);
    funcUser(); // John

    Burada func.bind(user) aslnda funcun this=user olarak balanm halidir.

    Tm argmanlar orjinal funca olduu gibi aktarlr, rnein:

    let user = {
      firstName: "John"
    };
    
    function func(phrase) {
      alert(phrase + ', ' + this.firstName);
    }
    
    // this'i user'a bala.
    let funcUser = func.bind(user);
    
    funcUser("Hello"); // Hello, John ("Hello" iletildi ve this=user oldu)

    Bunu obje metodu ile deneyecek olursak:

    let user = {
      firstName: "John",
      sayHi() {
        alert(`Hello, ${this.firstName}!`);
      }
    };
    
    let sayHi = user.sayHi.bind(user); // (*)
    
    sayHi(); // Hello, John!
    
    setTimeout(sayHi, 1000); // Hello, John!

    (*) satrnda user.sayHi metodunu alyoruz ve usera balyoruz. sayHi bu durumda balanm fonksiyon oluyor. Bylece tek bana arlabilir veya setTimeout ierisinde arlabilir. Nereden arld ok da nemli deildir. Kayna her zaman doru olacaktr.

    Grdnz gibi tm argmanlar olduu gibi iletilir, sadece this bind tarafndan sabitlenmitir:

    let user = {
      firstName: "John",
      say(phrase) {
        alert(`${phrase}, ${this.firstName}!`);
      }
    };
    
    let say = user.say.bind(user);
    
    say("Hello"); // Hello, John ("Hello" `say` fonksiyonuna iletildi)
    say("Bye"); // Bye, John ("Bye" `say` fonksiyonuna iletildi.)
    Kullanl metod: bindAll

    Eer bir objenin birok metodu var ise bunu aktif olarak gerekli yerlere iletip, bunlar bir dng ierisine alabiliriz:

    for (let key in user) {
      if (typeof user[key] == 'function') {
        user[key] = user[key].bind(user);
      }
    }

    Bu ekilde byk balama olaylar iin baz JavaScript ktphanelerinden yardm alnabilir. rnein lodash ,_.bindAll(obj) fonksiyonuna sahiptir.

    zet

    func.bind(kaynak, ...args) func fonksiyonunun "balanm hali"ni dndrr. Bu balanm halde this ve argmanlar sabitlenir.

    Bind genelde obje metodlarndaki thisin sabitlenmesi amacyla kullanlr, sonrasnda istenilen yere iletilebilir. setTimeout rnei gibi. bindin modern gelitirmede kullanlmasnn birok nedeni vardr bunlara ilerleyen konularda deineceiz.

    Grevler

    nem: 5

    Aadaki kodun kts nedir?

    function f() {
      alert( this ); // ?
    }
    
    let user = {
      g: f.bind(null)
    };
    
    user.g();
    zm

    Cevap: null.

    function f() {
      alert( this ); // null
    }
    
    let user = {
      g: f.bind(null)
    };
    
    user.g();

    Balanan fonksiyona dorudan deer atanmtr. Bundan dolay deitirilemez. Bundan dolay user.g() yi arsanz bile orjinal fonksiyon this=null eklinde arlacaktr.

    nem: 5

    Fazladan bir defa daha balama ilemi yaparak thisi deitirebilir miyiz?

    Aadaki kodun kts nedir?

    function f() {
      alert(this.name);
    }
    
    f = f.bind( {name: "John"} ).bind( {name: "Ann" } );
    
    f();
    zm

    Cevap: John.

    function f() {
      alert(this.name);
    }
    
    f = f.bind( {name: "John"} ).bind( {name: "Pete"} );
    
    f(); // John

    f.bind(...) tarafndan dnen egzotik objeler bound function yaratld zamanki kayna hatrlar. Bundan dolay bir fonksiyon birden fazla defa balanamaz.

    nem: 5

    Fonksiyonun zelliinde bir deer var. Bu deer bind edildikten sonra deiir mi? Neden?

    function sayHi() {
      alert( this.name );
    }
    sayHi.test = 5;
    
    let bound = sayHi.bind({
      name: "John"
    });
    
    alert( bound.test ); // kts ne olacak? neden?
    zm

    Cevap: undefined.

    bindn sonucu baka bir objedir. Bu objenin test zellii bulunmamaktadr.

    nem: 5

    askPassword() ars ifreyi kontrol etmeli ve buna gre user.loginOk veya user.loginFaili armaldr.

    Fakat bu bir hataya neden oluyor. Neden?

    Sadece st izili satrda deiiklik yaparak her eyin doru almasn salaynz. ( dier satrlarda deiiklik yaplmamaldr)

    function askPassword(ok, fail) {
      let password = prompt("Password?", '');
      if (password == "rockstar") ok();
      else fail();
    }
    
    let user = {
      name: 'John',
    
      loginOk() {
        alert(`${this.name} logged in`);
      },
    
      loginFail() {
        alert(`${this.name} failed to log in`);
      },
    
    };
    
    askPassword(user.loginOk, user.loginFail);
    zm

    Nedeni askn loginOk/loginFail fonksiyonlarn obje olmadan almasdr.

    Bunlar ardnda doal olarak this=undefined olarak alacaktr.

    Kayna balar isek:

    function askPassword(ok, fail) {
      let password = prompt("Password?", '');
      if (password == "rockstar") ok();
      else fail();
    }
    
    let user = {
      name: 'John',
    
      loginOk() {
        alert(`${this.name} logged in`);
      },
    
      loginFail() {
        alert(`${this.name} failed to log in`);
      },
    
    };
    
    askPassword(user.loginOk.bind(user), user.loginFail.bind(user));

    imdi alacaktr.

    Alternatif zm u ekilde olabilir:

    //...
    askPassword(() => user.loginOk(), () => user.loginFail());

    Genelde bu da alr. Fakat daha karmak durumlarda usern soru ve () => user.loginOk() arasnda zerine yazlabilir.

    Eitim haritas

    Yorumlar

    yorum yapmadan nce ltfen okuyun...
    • Eer gelitirme ile alakal bir neriniz var ise yorum yerine github konusu gnderiniz.
    • Eer makalede bir yeri anlamadysanz ltfen belirtiniz.
    • Koda birka satr eklemek iin <code> kullannz, birka satr eklemek iin ise <pre> kullann. Eer 10 satrdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)

    Web Proxy Viewer  |  New URL  |  Original Page