Javascript Call, Apply ve Bind Fonksiyonları Kullanımı

nhtctn nhtctn

Bu yazımda Javascriptteki call,apply ve bind fonksiyonlarını göstermeye çalışacağım. Yazıya başlamadan önce Javascriptteki Prototype mantığını ve this anahtar kelimesini iyice öğrenmenizi tavsiye ediyorum.

Javascript her ne kadar oldukça esnek bir dil olsa da, bazı zamanlar karın ağrısı çektiğimiz bir dil haline gelebiliyor. Javascript ile geliştirmeye yeni başlayanlar da ilk zamanlarda this anahtar kelimesinin kapsam alanını(scope) karıştırarak kodlarında sıkıntıya düşebiliyorlar. Şimdi ilk olarak, call,apply ve bind fonksiyonlarını göstermeden önce bir örnek ile this anahtar kelimesini hatırlatmak istiyorum.

Örneğin aşağıdaki gibi bir kod parçasında this bize global scopetaki(global kapsam) window objesini vermektedir. Çünkü Javascriptte global scopetaki objemiz window objesidir.

function test(){
  console.log(this) 
}
test();
// Console Çıktısı : > Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

Ancak her zaman this anahtar kelimesi bizim window objemizi göstermez. Şu örneğimize de bakalım.

function Person(){
	 this.showInfos = function(){
   	    console.log("Bu objemiz bir " + this.constructor.name + " objesidir");
   }
}
const person = new Person();

person.showInfos();

// Çıktı: Bu objemiz bir Person objesidir

Burada da Person constructorının içinde olduğumuz için Person objesi sonucunu aldık.

Ancak daha önceden söylediğim gibi, this anahtar kelimesinin bazı durumlarda kullanımı ve hangi objeyi gösterdiğini anlamak her zaman bu kadar kolay olmaz. Böyle durumlarda veya bir fonksiyonu farklı objeler üzerinde kullanmak istediğimiz zamanlarda, Javascript prototype objesinin içinde bulunan call,apply ve bind fonksiyonlarını kullanabiliriz.

Call ve Apply

Call ve Apply fonksiyonları Function objemizin __proto__ objesinde bulunan iki adet fonksiyondur. Bu fonksiyonların görevleri aynı olsa da kullanımları arasında ufak bir fark vardır. Şimdi ilk olarak Mozilla’nın dokümanlarından bu fonksiyonların ne iş yaptığını anlamaya çalışalım.

Call() fonksiyonu, verilen this anahtar değeriyle(obje) ve bağımsız olarak sağlanan bağımsız argümanlarla bir fonksiyonu çağırır. Argümanlar fonksiyona tek tek gönderilir. (Örnek: test(obj,arg1,arg2,arg3))

Apply() fonksiyonu, verilen this anahtar değeriyle(obje) ve bağımsız olarak sağlanan değişkenlerle bir fonksiyonu çağırır. Argümanlar fonksiyona argüman listesi şeklinde gönderilir. (Örnek: test(obj,[arg1,arg2,arg3]))

Bu fonksiyonların ne yaptığını anlamak için şu örneğimize bakalım.

const obj1 = {
    number1: 10,
    number2: 20,
}
const obj2 = {
    number1: 30,
    number2: 50,
}
function addNumbers(num){
		console.log(this.number1 + this.number2 + num );
}
addNumbers(100);
// Çıktı : NaN

Buradaki çıktının neden NaN olduğuyla ilgili bir fikri olan var mı ? Fikri olmayanlar için açıklamak gerekirse, şu anda global scope’ta bulunan objemiz window objesi olduğu için ve this anahtar kelimesi bu objeyi gösterdiği için bu sonucu aldık. Window objesinin içinde number1 veya number2 şeklinde property bulunmuyor. Bu nedenle aslında “undefined + undefined + 100” gibi bir toplama yapıyoruz ve bunun sonucunda “NaN” sonucunu elde ediyoruz.

Peki bu örnekte addNumbers fonksiyonunun hem obj1 hem de obj2 objesi için çalışmasını istersek ne yapabiliriz ? İşte burada yardımımıza call ve apply fonksiyonları koşuyor. Burada, yukarıdaki tanımlara göre call veya apply fonksiyonlarını kullanırsak this anahtar kelimesi, call fonksiyonuna hangi objeyi argüman olarak gönderirsek onu gösterecektir.

const obj1 = {
    number1:10,
    number2:20
}
const obj2 = {
    number1:30,
    number2:50
}

function addNumbers(num) {
    console.log(this.number1 + this.number2 + num);

}

addNumbers.call(obj1,100);
addNumbers.call(obj2,100);

// Çıktı: 130 180

Burada call metoduna birinci argüman olarak obj1’i gönderdiğimizde this anahtar kelimesi bu objeyi gösterdiği için sonucumuz 130 çıktı. Aynı şekilde, obj2’i gönderdiğimizde de 180 sonucunu aldık.Yani, bir fonksiyonu call fonksiyonuyla farklı objeler ile kullanabildik. Şimdi de bu kullanımı apply metoduyla yapmaya çalışalım.

const obj1 = {
    number1:10,
    number2:20
}
const obj2 = {
    number1:30,
    number2:50
}

function addNumbers(num) {
    console.log(this.number1 + this.number2 + num);

}

addNumbers.apply(obj1,[100]);
addNumbers.apply(obj2,[100]);

Peki biz bu fonksiyonları nerelerde kullanabiliriz ? Örneğin, Prototype tabanlı kalıtım yaparken bu fonksiyonlar oldukça yararlı olacaktır.

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

function Employee(name,age){
    // This Employee'yi Gösteriyor 
    // ES6 sınıflarında kullandığımız super() gibi Person yapıcı metodunu kullanıyoruz.
    Person.call(this,name); 
    this.age = age;

}
const emp1 = new Employee("Mustafa",25);

console.log(emp1.name);
console.log(emp1.age);

// Çıktı : Mustafa 25

Burada ES6 sınıflarında kullandığımız super() gibi, Person yapıcı metodunu call fonksiyonu sayesinde kendi objemizin yapıcı metodu içinde çağırabiliriz.

Bind Fonksiyonu

Bind fonksiyonu da mantık olarak call ve apply fonksiyonlarına oldukça fazla benzer. Ancak kullanım olarak bu fonksiyonlardan farklıdır. Aşağıda kendi yaptığım tanımı görebilirsiniz.

Bind() fonksiyonu, içine verilen objeye göre yeni bir fonksiyon kopyası yaratır. Oluşan bu kopya fonksiyonu daha sonradan argüman listesi ile beraber gönderilen objeye kullanabiliriz.

Hiçbir şey anlamadık değil mi ? Anlamak için örneğimize bakalım.

const obj1 = {
    number1:10,
    number2:20
};

function getNumbersTotal(number3,number4) {
    return this.number1 + this.number2 + number3 + number4;
}
// obj1'i this parametresinin göstereceği şekilde bağlayarak yeni bir fonksiyon oluşturuyoruz.

const copyFunc = getNumbersTotal.bind(obj1);

console.log(copyFunc(30,40));

// Çıktı : 100

Burada da bind fonksiyonunun kullanımını görüyoruz. Aslında mantık olarak call ve apply’a benzese de yapı olarak epey farklı. Call ve Apply fonksiyonları bir fonksiyonu hemen çalıştırırken, bind fonksiyonu bize yeni bir kopya üretmektedir. Oluşturulan bu kopyayı ise istediğimiz herhangi bir bağlamda(context) kullanabiliriz.

Aklınızda şu şekilde bir sorunun döndüğünü tahmin ediyorum.

“Bind, Call ve Apply mantık olarak aynıysa hangisini nerelerde kullanacağım ?

Javascript’e yeni başlayanların bu soruyu sorması oldukça normal. Cevabını şu şekilde verebiliriz.

Bind fonksiyonundan, fonksiyonumuzu başka bir bağlamda daha sonradan kullanabilmek adına yararlanabiliriz (örnek,Javascript Olayları — JS Events). Call ve Apply Fonksiyonlarını ise bir fonksiyonu hemen bir obje ile çağırmak için kullanabiliriz.

Bu söylediklerim sizin için biraz havada kalabilir. Ancak bu fonksiyonları Javascriptte ilerledikçe nerelerde kullanabileceğinizi çok daha iyi bir şekilde anlayacaksınız.

Kaynak: https://medium.com/yaz%C4%B1l%C4%B1m-bilimi/javascript-call-apply-ve-bind-fonksiyonlar%C4%B1-3b0242fbc7dd

Yorum yazın

BENZER YAZILAR