JavaScript'te this, bir kod parçasının hangi bağlamda çalıştığını gösteren özel bir anahtar kelimedir ve değeri normal fonksiyonlarda fonksiyonun nasıl tanımlandığına değil, nasıl çağrıldığına göre belirlenir. obj.metot() şeklindeki çağrıda this, obj olur; nesneye bağlı olmadan yapılan fonk() çağrısında strict mode'da undefined, strict olmayan kodda global nesne olur. call(), apply() ve bind() ile this değerini kendiniz verebilirsiniz; arrow function ise this değerini tanımlandığı kapsamdan alır.

MDN, this değerini fonksiyonun gizli bir parametresi gibi düşünmeyi önerir: Siz parametre listesine yazmasanız da dil, her çağrıda bu bağlamayı sizin için oluşturur. Aşağıda bütün bağlamları (metot, bağımsız çağrı, callback, arrow function, kurucu, sınıf, global ve modül) tek tek çalıştırılmış örneklerle ele alıyoruz. Fonksiyon türleri arasındaki genel farklar için fonksiyon türleri yazısına bakabilirsiniz.

Metot çağrısı: noktanın solundaki nesne

Metot çağrısı: noktanın solundaki nesne

Normal bir fonksiyon nesne.fonk() biçiminde çağrıldığında this, noktanın solundaki nesnedir. Aynı fonksiyonu iki farklı nesneye bağlarsanız, her çağrıda farklı bir this görürsünüz:

javascript
function kimim() {
  return this.ad;
}

const kedi = { ad: "Tekir", kimim };
const kopek = { ad: "Karabaş", kimim };

console.log(kedi.kimim()); // Tekir
console.log(kopek.kimim()); // Karabaş

Burada önemli olan, fonksiyonun hangi nesnenin özelliği olarak oluşturulduğu değil, çağrının hangi nesne üzerinden yapıldığıdır. MDN, prototip zincirinden gelen bir metotta bile this değerinin çağrıyı yapan nesne olduğunu vurgular. Prototip zinciri için prototip ve kalıtım yazısına göz atabilirsiniz.

Bağımsız çağrı ve kaybolan this

Bir metodu nesneden koparıp bir değişkene atadığınızda ve o değişkeni çağırdığınızda, çağrıda artık nokta yoktur. Strict mode'da this undefined olur ve özelliğe erişim hata verir:

javascript
"use strict";

const kullanici = {
  ad: "Zeynep",
  selamla() {
    return `Merhaba ${this.ad}`;
  },
};

console.log(kullanici.selamla()); // Merhaba Zeynep

const ayrik = kullanici.selamla;
try {
  ayrik();
} catch (e) {
  console.log(e.name + ": " + e.message);
  // TypeError: Cannot read properties of undefined (reading 'ad')
}

Strict olmayan kodda ise dil, this yerine koyma (this substitution) adı verilen bir işlem yapar: undefined ya da null gelen this değeri globalThis ile, ilkel bir değer ise onun sarmalayıcı nesnesiyle değiştirilir. Bu yüzden aynı kod hata vermez ama sessizce yanlış sonuç üretebilir. Strict mode'da bu dönüşüm yapılmaz:

javascript
function tur() {
  return Object.prototype.toString.call(this);
}
console.log(tur.call(7)); // [object Number]
console.log(tur.call("metin")); // [object String]
console.log(tur.call(undefined) === Object.prototype.toString.call(globalThis)); // true

function katiTur() {
  "use strict";
  return typeof this;
}
console.log(katiTur.call(7)); // number
console.log(katiTur()); // undefined

call(), apply() ve bind()

call(), apply() ve bind(): call(thisArg, a, b), apply(thisArg, [a, b]), bind(thisArg, a)

Bu üç metot, this değerini çağrı sırasında açıkça vermenizi sağlar. call(thisArg, arg1, arg2) fonksiyonu hemen çağırır ve argümanları tek tek alır. apply(thisArg, dizi) da hemen çağırır ama argümanları dizi ya da dizi benzeri bir nesne olarak alır. bind(thisArg, ...) ise fonksiyonu çağırmaz; this değeri ve isterseniz ilk birkaç argümanı sabitlenmiş yeni bir fonksiyon (bound function) döndürür:

javascript
function tanit(sehir, yil) {
  return `${this.ad} / ${sehir} / ${yil}`;
}
const kisi = { ad: "Mert" };

console.log(tanit.call(kisi, "İzmir", 2024)); // Mert / İzmir / 2024
console.log(tanit.apply(kisi, ["Bursa", 2025])); // Mert / Bursa / 2025

const bagli = tanit.bind(kisi, "Ankara");
console.log(bagli(2026)); // Mert / Ankara / 2026
console.log(bagli.name, bagli.length); // bound tanit 1

MDN'ye göre bağlanmış fonksiyonun name değeri hedef fonksiyonun adının başına "bound " eklenerek oluşur, length değeri de hedefin length değerinden sabitlenen argüman sayısı çıkarılarak bulunur (en az 0). Bir başka önemli kural: bind yalnızca bir kez etkilidir. Bağlanmış bir fonksiyonu tekrar bağlamak ya da call ile çağırmak this değerini değiştirmez:

javascript
function oku() {
  return this.deger;
}

const g = oku.bind({ deger: "ilk" });
const h = g.bind({ deger: "ikinci" });

console.log(g()); // ilk
console.log(h()); // ilk
console.log(g.call({ deger: "call ile" })); // ilk
MetotFonksiyonu çağırır mıArgümanlarDöndürdüğü
call(thisArg, a, b)Evet, hemenTek tek listeFonksiyonun sonucu
apply(thisArg, [a, b])Evet, hemenDizi veya dizi benzeriFonksiyonun sonucu
bind(thisArg, a)HayırÖnden sabitlenirYeni bound function

Günümüz kodunda apply çoğu zaman spread sözdizimiyle yer değiştirir: fn.apply(null, args) ile fn(...args) genellikle aynı işi görür. MDN, call ve apply ile kurucu zincirlemenin (kalıtım kurmanın) yapılmamasını, bunun yerine extends ya da Reflect.construct() kullanılmasını önerir.

Callback içinde this

Bir fonksiyonu callback olarak verdiğinizde this değerini, callback'i çağıran API belirler. Dizi metotları gibi pek çok API callback'i nesneye bağlamadan çağırır; yani strict mode'da this undefined olur. Dizi metotlarının çoğu, this değerini vermeniz için isteğe bağlı ikinci bir thisArg parametresi alır:

javascript
"use strict";
function yaz() {
  return this === undefined ? "undefined" : this.etiket;
}

console.log([1, 2].map(yaz)); // [ 'undefined', 'undefined' ]
console.log([1, 2].map(yaz, { etiket: "thisArg" })); // [ 'thisArg', 'thisArg' ]

Callback konusunun geri kalanını, senkron ve asenkron callback farkını callback fonksiyonlar yazısında bulabilirsiniz.

Arrow function: dıştaki this korunur

Arrow function kendi this bağlamasını oluşturmaz; tanımlandığı yerin this değerini closure ile yakalar. Bu, bir metodun içinde zamanlayıcı ya da callback yazarken çok işe yarar. Aşağıdaki örnekte arrow function metodun this değerini korur; normal fonksiyon ise başka bir değer görür (Node.js'te setTimeout callback'i kendi zamanlayıcı nesnesiyle çağrılır):

javascript
const zamanlayici = {
  sayi: 0,
  baslat() {
    setTimeout(() => {
      this.sayi++;
      console.log("ok fonksiyon:", this.sayi); // ok fonksiyon: 1
    }, 10);
    setTimeout(function () {
      console.log("normal fonksiyon:", this === zamanlayici); // normal fonksiyon: false
    }, 20);
  },
};
zamanlayici.baslat();

const disari = () => this;
console.log(disari.call({ x: 1 }) === disari()); // true

Son satır, call ile verilen thisArg değerinin arrow function'da yok sayıldığını gösterir. MDN'nin ifadesiyle arrow function'lar bir anlamda "otomatik bağlanmış" gibi davranır. Bu yakalama mekanizmasının kendisi bir closure'dır; konuyu closure yazısında ayrıntılı işliyoruz.

Kurucu fonksiyonlar ve sınıflar

Bir fonksiyon new ile çağrıldığında this, yeni oluşturulan nesneye bağlanır ve bu nesne new ifadesinin sonucu olur. Kurucu ilkel olmayan başka bir değer (örneğin bir nesne) döndürürse, this ile hazırlanan nesne atılır:

javascript
function Urun(ad) {
  this.ad = ad;
}
function Ozel(ad) {
  this.ad = ad;
  return { ad: "başka nesne" };
}
console.log(new Urun("kalem").ad); // kalem
console.log(new Ozel("kalem").ad); // başka nesne

Sınıflarda kurucu, metotlar ve örnek alanı (instance field) başlatıcıları örnek bağlamındadır; this oluşturulan örnektir. Statik metotlarda ve statik alanlarda this sınıfın kendisidir. Sınıf alanına atanmış bir arrow function bu yüzden örneğe bağlı kalır ve nesneden koparılsa bile çalışır; normal metot ise koparıldığında this değerini kaybeder:

javascript
class Sayac {
  deger = 0;
  arttir = () => {
    this.deger++;
    return this.deger;
  };
  normal() {
    return this === undefined ? "this undefined" : this.deger;
  }
}

const s = new Sayac();
const { arttir, normal } = s;
console.log(arttir()); // 1
console.log(arttir()); // 2
console.log(normal()); // this undefined
console.log(s.normal()); // 2

Global kapsam, Node.js ve modüller

Fonksiyon dışındaki this değeri kodun nasıl yüklendiğine bağlıdır. Tarayıcıdaki klasik bir script'in en üst düzeyinde this, globalThis değeridir. ES modülünün en üst düzeyinde ise this her zaman undefined olur. Node.js'in CommonJS modülleri bir fonksiyonla sarılarak çalıştığı için en üst düzeydeki this, module.exports nesnesidir. Node.js 24 ile iki dosyayı çalıştırdığımızda sonuç şöyle:

javascript
// ornek.js (CommonJS)
console.log(this === module.exports); // true

// ornek.mjs (ES modülü)
console.log(this); // undefined

Nesne literalleri kendi this kapsamını oluşturmaz; { a: this } yazdığınızda this, nesnenin yazıldığı yerdeki değeri alır. Modüllerin genel yapısı için ES modülleri yazısına bakabilirsiniz.

Özet tablo: this neye eşit?

Çağrı biçimithis değeri
obj.metot()obj
fonk() strict modeundefined
fonk() strict olmayan kodglobalThis
fonk.call(x) veya fonk.apply(x)x (strict olmayan kodda ilkel değerler nesneye çevrilir)
fonk.bind(x)()x, sonradan değiştirilemez
new Fonk()Yeni oluşturulan nesne
Arrow functionTanımlandığı yerin this değeri
Sınıf statik metoduSınıfın kendisi
ES modülü en üst düzeyundefined
Node.js CommonJS en üst düzeymodule.exports

Sık yapılan hatalar

Sık yapılan hatalar: Metodu callback olarak vermek (setTimeout(nesne.metot, 100)) ve this değerinin..., Nesne metodunu arrow function olarak tanımlamak., Bağlanmış bir fonksiyonu...
  • Metodu callback olarak vermek (setTimeout(nesne.metot, 100)) ve this değerinin korunacağını sanmak. Çözüm nesne.metot.bind(nesne) ya da () => nesne.metot() yazmaktır.
  • Nesne metodunu arrow function olarak tanımlamak.
  • Bağlanmış bir fonksiyonu tekrar bind ile farklı bir nesneye bağlamaya çalışmak.
  • Node.js'te dosyanın en üstünde this değerinin globalThis olduğunu varsaymak.
  • this değerini call ile değiştirmek için arrow function kullanmak.

Sık Sorulan Sorular

this neden bazen undefined oluyor?

Fonksiyon strict mode'da çalışıyor ve bir nesneye bağlı olmadan çağrılıyorsa this undefined olur. Sınıf gövdeleri ve modüller otomatik olarak strict mode'da olduğu için koparılan sınıf metotlarında bu durumla sık karşılaşırsınız.

call ile apply arasındaki fark nedir?

İkisi de fonksiyonu hemen çağırır ve ilk argümanı this olarak kullanır. Fark yalnızca diğer argümanların verilişindedir: call onları tek tek, apply bir dizi ya da dizi benzeri nesne içinde alır.

bind ile arrow function aynı işi mi görür?

Sonuç benzer olabilir: İkisi de this değerini sabit tutar. Ama bind mevcut bir fonksiyondan yeni bir fonksiyon üretir ve isterseniz argüman da sabitler; arrow function ise tanımlandığı yerin this değerini kullanır ve kendi arguments nesnesi yoktur.

Bound function new ile kullanılabilir mi?

Hedef fonksiyon kurucu olabiliyorsa evet. MDN'ye göre bu durumda bind ile verilen this değeri yok sayılır, önden sabitlenen argümanlar ise normal şekilde aktarılır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: JavaScript öğrenme rehberi · Fonksiyon türleri · Closure nedir · JavaScript class · Strict mode · Callback fonksiyonlar