Kısa cevap: element.addEventListener("click", dinleyici, secenekler) çağrısı, belirtilen türde bir olay o hedefe ulaştığında çalışacak bir fonksiyon kaydeder. Üçüncü parametre bir nesne olabilir ve dört seçenek alır: dinleyiciyi bir kez çalıştırıp otomatik silen once, tarayıcıya preventDefault() çağrılmayacağını söyleyen passive, dinleyiciyi yakalama evresine taşıyan capture ve bir AbortController ile dinleyiciyi topluca kaldırmaya yarayan signal. Kaydı silmek için removeEventListener() aynı tür, aynı fonksiyon referansı ve aynı capture değeriyle çağrılır.
Bu yazıda MDN referansına dayanarak addEventListener() imzasını, her seçeneğin varsayılan değerini, dinleyici içinde this değerinin neye bağlandığını, olay nesnesinin en sık kullanılan özelliklerini ve bellek ile kaldırma konusundaki tipik hataları anlatıyoruz. Olayın DOM ağacında nasıl yayıldığı, stopPropagation() ve olay delegasyonu ayrı bir konudur; onlar için event bubbling, capturing ve delegation yazısına bakın. Bu sayfa serinin bir parçasıdır, tüm konuların listesi Web API öğrenme rehberi sayfasında.
addEventListener ne yapar?
addEventListener(), EventTarget arayüzünün bir yöntemidir. MDN bu arayüzü olay alabilen ve dinleyici barındırabilen her nesnenin ortak tabanı olarak tanımlar. En bilinen hedefler Element, Document ve Window olsa da IDBRequest ya da AudioContext gibi DOM dışı nesneler de olay hedefidir. Bu yüzden aynı yöntemi bir düğmede, belgenin kendisinde, pencerede veya kendi yazdığınız bir sınıfta aynı şekilde kullanırsınız.
Yöntem, verdiğiniz fonksiyonu ya da handleEvent() yöntemi olan bir nesneyi, o hedefin o olay türüne ait dinleyici listesine ekler. Önemli bir ayrıntı: Aynı fonksiyon aynı hedefe, aynı tür ve aynı capture değeriyle zaten eklenmişse ikinci kez eklenmez. Buna karşılık her çağrıda yeniden yazılan anonim fonksiyonlar, kaynak kodu birebir aynı olsa bile, her seferinde yeni bir fonksiyon nesnesi olduğu için ayrı ayrı eklenir. MDN bunun döngü içinde bile geçerli olduğunu özellikle vurgular.
const hedef = new EventTarget();
let sayac = 0;
function say() {
sayac++;
}
hedef.addEventListener("ping", say);
hedef.addEventListener("ping", say); // aynı referans, ikinci kez eklenmez
hedef.dispatchEvent(new Event("ping"));
console.log(sayac); // 1
let anonim = 0;
for (let i = 0; i < 2; i++) {
hedef.addEventListener("pong", () => {
anonim++;
});
}
hedef.dispatchEvent(new Event("pong"));
console.log(anonim); // 2Yukarıdaki örnek yalnızca standart EventTarget ve Event sınıflarını kullandığı için tarayıcıda da aynı şekilde çalışır; biz onu Node.js 24.4.0 ile çalıştırıp çıktıları doğruladık. Kendi olaylarınızı üretmek ve göndermek konusu CustomEvent ve EventTarget yazısında ayrıntılı işleniyor.
Sözdizimi ve parametreler

MDN üç çağrı biçimi listeler: yalnızca tür ve dinleyici, tür, dinleyici ve seçenek nesnesi, ya da eski stilde tür, dinleyici ve tek bir boolean değer olan useCapture. Yöntem bir şey döndürmez, dönüş değeri undefined olur.
addEventListener(type, listener)
addEventListener(type, listener, options)
addEventListener(type, listener, useCapture)- type: Dinlenecek olay türünün adı. Büyük ve küçük harfe duyarlıdır;
"click"ile"Click"farklı türlerdir. - listener: Olay geldiğinde çağrılacak fonksiyon,
handleEvent()yöntemi olan bir nesne ya danull. - options:
capture,once,passivevesignalalanlarını içerebilen nesne. - useCapture: Seçenek nesnesi yerine verilen boolean. Belirtilmezse
falsekabul edilir.
| Seçenek | Varsayılan | Ne yapar |
|---|---|---|
| capture | false | Dinleyiciyi yakalama evresinde, hedefin altındaki öğelerden önce çalıştırır |
| once | false | Dinleyici en fazla bir kez çağrılır, çağrıldığında otomatik olarak kaldırılır |
| passive | false (bazı istisnalarla true) | Dinleyicinin preventDefault çağırmayacağını bildirir, çağrılırsa etkisiz kalır |
| signal | yok | Bağlı AbortController üzerinde abort çağrıldığında dinleyici kaldırılır |
once: tek seferlik dinleyici
once: true verildiğinde dinleyici ilk çağrısından hemen sonra listeden çıkarılır. Bir karşılama mesajını yalnızca ilk tıklamada göstermek, bir kurulum adımını bir kez tetiklemek gibi durumlar için uygundur. Elle removeEventListener() çağırmanıza gerek kalmaz. MDN örneklerinden biri once ile passive seçeneklerini aynı nesnede birlikte kullanır; seçenekler birbirini dışlamaz, istediğiniz kadarını birleştirebilirsiniz.
signal: AbortController ile toplu kaldırma
signal seçeneğine bir AbortSignal verirseniz, o sinyalin sahibi olan AbortController üzerinde abort() çağrıldığı anda dinleyici kaldırılır. Bu yöntemin en büyük avantajı, aynı sinyali birden fazla addEventListener() çağrısına verip hepsini tek satırla temizleyebilmenizdir. Böylece her dinleyici için fonksiyon referansı saklamak zorunda kalmazsınız ve anonim fonksiyon kullansanız bile kaldırma mümkün olur.
const hedef = new EventTarget();
let tekSefer = 0;
hedef.addEventListener("kaydet", () => tekSefer++, { once: true });
hedef.dispatchEvent(new Event("kaydet"));
hedef.dispatchEvent(new Event("kaydet"));
console.log(tekSefer); // 1
const controller = new AbortController();
let a = 0;
let b = 0;
hedef.addEventListener("tik", () => a++, { signal: controller.signal });
hedef.addEventListener("tak", () => b++, { signal: controller.signal });
hedef.dispatchEvent(new Event("tik"));
hedef.dispatchEvent(new Event("tak"));
controller.abort(); // bu sinyalle eklenen tüm dinleyiciler kaldırılır
hedef.dispatchEvent(new Event("tik"));
hedef.dispatchEvent(new Event("tak"));
console.log(a, b); // 1 1Sayfada bu desen genellikle bir bileşenin ya da bir modal pencerenin ömrüyle birlikte kullanılır: Bileşen açılırken bir AbortController oluşturursunuz, belgeye ve pencereye eklediğiniz bütün dinleyicilere aynı sinyali verirsiniz, bileşen kapanırken tek bir abort() çağrısıyla hepsini sökersiniz. Aynı sinyal fetch() isteklerini iptal etmek için de kullanılabilir; ağ tarafı için Fetch API yazısına bakın.
passive: kaydırma performansı

Bazı olayların bir varsayılan eylemi vardır; örneğin wheel olayı varsayılan olarak kapsayıcıyı kaydırır. Tarayıcı, dinleyicinin preventDefault() çağırıp çağırmayacağını önceden bilemediği için kaydırmayı başlatmadan önce dinleyicinin bitmesini beklemek zorunda kalır. Dinleyici uzun sürerse kullanıcı kaydırmada belirgin bir gecikme hisseder. passive: true ile dinleyici, varsayılan eylemi iptal etmeyeceğini baştan bildirir ve tarayıcı beklemeden kaydırmaya başlar. Pasif bir dinleyici yine de preventDefault() çağırırsa hiçbir şey olmaz, tarayıcı konsola bir uyarı yazabilir.
Burada dikkat edilmesi gereken bir istisna var. Spesifikasyon, eski kodlarda da kaydırma kazancı sağlamak için wheel, mousewheel, touchstart ve touchmove olaylarında, hedef Window, Document, document.documentElement ya da document.body olduğunda passive varsayılanını true kabul eder. Bu hedeflerde kaydırmayı gerçekten engellemek istiyorsanız passive: false değerini açıkça yazmanız gerekir; varsayılana güvenmek bu durumda işe yaramaz. Sıradan scroll olayı ise iptal edilemediği için bu ayar onu etkilemez.
const container = document.querySelector("#container");
// Kaydırmayı engellemeyecek, tarayıcı beklemeden kaydırır
container.addEventListener("wheel", kaydirmaIzle, { passive: true });
// Belge düzeyinde kaydırmayı gerçekten engellemek için açıkça false yazılır
document.addEventListener(
"touchmove",
(event) => {
event.preventDefault();
},
{ passive: false },
);
function kaydirmaIzle(event) {
// yalnızca okuma yapar, preventDefault çağırmaz
}capture: yakalama evresinde dinlemek
capture: true verilen dinleyici, olay hedefe inerken yakalama evresinde çalışır; yani iç öğedeki dinleyicilerden önce tetiklenir. Varsayılan durumda dinleyiciler kabarcıklanma evresinde çağrılır. Dinleyiciyi doğrudan olayın hedefine eklediyseniz, olay o noktada hedef evresindedir. Bu evrelerin sırası, hangi olayların kabarcıklandığı ve yayılmanın nasıl durdurulduğu olay yayılımı yazısının konusudur; burada yalnızca şunu bilmeniz yeterli: capture değeri, aynı fonksiyonun aynı türe iki ayrı kayıt olarak eklenmesine izin veren tek seçenektir ve kaldırma sırasında da bu değerin eşleşmesi gerekir.
removeEventListener ile kaldırma kuralları
removeEventListener() bir kaydı tür, dinleyici fonksiyonu ve capture bayrağının birleşimine bakarak bulur. Hiçbir kayıtla eşleşmeyen bir çağrı hata vermez, sessizce hiçbir şey yapmaz. Bu sessizlik en sık yapılan hatanın da kaynağıdır: Kaldırma çalışmadığında tarayıcı sizi uyarmaz, dinleyici çalışmaya devam eder. MDN eşleşme kuralını açıkça yazar: once, passive ve signal eşleşmeyi etkilemez, yalnızca capture değeri aynı olmalıdır.
const hedef = new EventTarget();
let n = 0;
function dinle() {
n++;
}
hedef.addEventListener("x", dinle, true);
hedef.removeEventListener("x", dinle, false); // eşleşmez
hedef.dispatchEvent(new Event("x"));
console.log(n); // 1
hedef.removeEventListener("x", dinle, { capture: true }); // eşleşir
hedef.dispatchEvent(new Event("x"));
console.log(n); // 1
hedef.addEventListener("y", dinle, { passive: true });
hedef.removeEventListener("y", dinle, { passive: false }); // yine eşleşir
hedef.dispatchEvent(new Event("y"));
console.log(n); // 1MDN ayrıca bazı tarayıcı sürümlerinin bu konuda geçmişte tutarsız davrandığını not eder ve özel bir nedeniniz yoksa kaldırırken eklerken kullandığınız değerlerin aynısını vermenizi önerir. Bir dinleyici hem capture açık hem kapalı olarak iki kez eklendiyse, ikisini ayrı ayrı kaldırmanız gerekir. Bir olay işlenirken aynı hedefteki başka bir dinleyiciyi kaldırırsanız, kaldırılan dinleyici o olay için artık çağrılmaz.
Dinleyici içinde this ve currentTarget
addEventListener() ile normal bir function eklediğinizde, fonksiyonun içindeki this değeri dinleyicinin bağlı olduğu öğeyi gösterir ve olay nesnesinin currentTarget özelliğiyle aynıdır. Ok fonksiyonlarının kendi this bağlamı yoktur, dışarıdaki bağlamı kullanırlar; bu yüzden ok fonksiyonu içinde this öğeyi göstermez. Hangisini kullanırsanız kullanın, güvenli yol event.currentTarget okumaktır. Dilin this kuralları için JavaScript öğrenme rehberine bakabilirsiniz.
Bir sınıf içinde dinleyici yazarken sınıf örneğine erişmeniz gerekir. MDN bunun için üç yol gösterir: Yöntemi yapıcıda bind(this) ile bağlamak, yöntemi bir ok fonksiyonu içinden çağırmak ya da nesnenin kendisini dinleyici olarak verip handleEvent() yöntemini tanımlamak. Son yöntemde this doğrudan sınıf örneğidir ve tek bir yöntem birden çok olay türünü event.type ile ayırt edebilir.
class Sepet {
adet = 0;
constructor(hedef) {
// dinleyici olarak nesnenin kendisi veriliyor
hedef.addEventListener("ekle", this);
hedef.addEventListener("cikar", this);
}
handleEvent(event) {
switch (event.type) {
case "ekle":
this.adet++;
break;
case "cikar":
this.adet--;
break;
}
}
}
const hedef = new EventTarget();
const sepet = new Sepet(hedef);
hedef.dispatchEvent(new Event("ekle"));
hedef.dispatchEvent(new Event("ekle"));
hedef.dispatchEvent(new Event("cikar"));
console.log(sepet.adet); // 1
hedef.addEventListener("kontrol", function (e) {
console.log(this === e.currentTarget); // true
});
hedef.dispatchEvent(new Event("kontrol"));bind() kullandığınızda dikkat etmeniz gereken nokta, bind() her çağrıldığında yeni bir fonksiyon döndürmesidir. Kaldırma yapacaksanız bağlanmış fonksiyonu bir kez oluşturup saklamalı, hem ekleme hem kaldırmada o referansı kullanmalısınız. MDN örneğinde bu yüzden yapıcıda this.onclick2 = this.onclick2.bind(this) satırı bulunur.
Olay nesnesinde en çok kullanılan alanlar

Dinleyici tek bir argüman alır: Event arayüzünden ya da ondan türeyen bir arayüzden (örneğin MouseEvent, KeyboardEvent, PointerEvent, SubmitEvent) bir nesne. Dönüş değeri yok sayılır. Dinleyiciye veri taşımak ya da ondan veri almak için parametre ve dönüş değeri yerine kapanışları (closure) kullanırsınız; dış kapsamdaki değişkenler dinleyiciden okunabilir ve değiştirilebilir.
| Özellik veya yöntem | Anlamı |
|---|---|
| type | Olayın türü, örneğin click veya load |
| target | Olayın ilk gönderildiği nesne |
| currentTarget | Şu anda çalışan dinleyicinin bağlı olduğu nesne, dinleyici dışında null |
| isTrusted | Olay tarayıcı tarafından üretildiyse true, dispatchEvent ile gönderildiyse false |
| timeStamp | Olayın oluşturulduğu an, zaman kökeninden itibaren milisaniye |
| defaultPrevented | preventDefault çağrılıp olay iptal edildiyse true |
| preventDefault() | İptal edilebilir olayın varsayılan eylemini engeller |
| stopPropagation() | Olayın diğer öğelere yayılmasını durdurur |
currentTarget ile ilgili sık atlanan bir kural var: Bu değer yalnızca dinleyici çalışırken doludur. Olay nesnesini bir değişkende saklayıp dinleyici bittikten sonra okursanız null görürsünüz. Asenkron bir işlemden sonra öğeye ihtiyaç duyacaksanız, öğeyi dinleyici içinde ayrı bir değişkene alın. isTrusted ise kullanıcı eylemlerinden ve tarayıcının kendi ürettiği olaylardan gelirse true, betikle gönderilen olaylarda false olur; MDN, HTMLElement.click() ile tetiklenen click olayında da false olduğunu belirtir.
const hedef = new EventTarget();
let sakla;
hedef.addEventListener("bak", (e) => {
sakla = e;
console.log(e.currentTarget === hedef); // true
});
hedef.dispatchEvent(new Event("bak"));
console.log(sakla.currentTarget); // null
console.log(sakla.type); // bak
console.log(sakla.isTrusted); // false
console.log(sakla.target === hedef); // trueonclick özelliği ile addEventListener farkı
MDN olay işleyici kaydetmek için iki önerilen yol tanımlar: onclick gibi bir onevent özelliğine fonksiyon atamak ya da addEventListener() kullanmak. Üçüncü yol olan HTML içine onclick="..." özniteliği yazmak ise önerilmez; işaretlemeyi şişirir ve hata ayıklamayı zorlaştırır. onevent özelliği ile HTML özniteliği aynı tek yuvayı paylaşır; bu yuvaya yeni bir fonksiyon atamak eskisinin yerine geçer. addEventListener() ile eklenenler ise bu yuvadan bağımsızdır, birbirini silmez.
| Konu | onclick özelliği | addEventListener |
|---|---|---|
| Aynı olaya birden çok işleyici | Hayır, son atanan geçerli | Evet, eklendikleri sırayla çalışır |
| Yakalama evresi | Hayır | Evet, capture ile |
| once, passive, signal | Yok | Var |
| Kaldırma | null atanarak | removeEventListener veya abort |
| DOM dışı hedefler | Yalnızca tanımlıysa | Her EventTarget üzerinde |
Sıralama konusunda da MDN bir kural verir: Aynı evre içinde dinleyiciler kaydedildikleri sırayla çalışır. onevent işleyicisi sıraya ilk kez null dışı bir değer aldığında girer; sonradan başka bir fonksiyon atamanız yalnızca çağrılacak fonksiyonu değiştirir, sıradaki yerini değiştirmez.
Uygulamalı mini örnek: tek seferlik bildirim ve temizlik
Aşağıdaki örnek bir bilgi kutusunu ele alır. Kapatma düğmesi yalnızca bir kez çalışmalıdır; kutu açıkken Escape tuşu ve sayfa genelindeki tıklamalar da dinlenir. Kutu kapandığında tüm dinleyiciler tek bir abort() ile kaldırılır. Bu kod tarayıcıya özgüdür, MDN sayfalarındaki API adlarına göre yazıldı ve çalıştırılmadı.
<div id="bilgi" role="status">
Yeni sürüm yayında.
<button type="button" id="kapat">Kapat</button>
</div>const kutu = document.getElementById("bilgi");
const kapat = document.getElementById("kapat");
const controller = new AbortController();
const { signal } = controller;
function kutuyuKapat() {
kutu.remove();
controller.abort(); // aşağıdaki üç dinleyici birlikte kaldırılır
}
kapat.addEventListener("click", kutuyuKapat, { once: true, signal });
document.addEventListener(
"keydown",
(event) => {
if (event.key === "Escape") {
kutuyuKapat();
}
},
{ signal },
);
document.addEventListener(
"click",
(event) => {
if (!kutu.contains(event.target)) {
kutuyuKapat();
}
},
{ signal },
);Klavye olayında event.key değerinin nasıl hesaplandığını ve neden keyCode yerine tercih edildiğini klavye olayları yazısında, fare ve dokunmatik girdiyi tek modelde ele almayı pointer events yazısında bulabilirsiniz.
Sık yapılan hatalar
- Fonksiyonu çağırarak vermek:
addEventListener("click", kaydet())yazmakkaydetfonksiyonunu hemen çalıştırır ve dönüş değerini dinleyici olarak verir. Doğrusukaydetreferansını parantezsiz vermektir. - Tür adını yanlış yazmak: Tür büyük ve küçük harfe duyarlıdır ve
onöneki almaz;"onclick"değil"click"yazılır.DOMContentLoadedgibi karışık harfli adlar da birebir yazılmalıdır. - Döngüde anonim dinleyici üretmek: MDN bellek bölümünde, döngünün her turunda yeni bir anonim fonksiyon oluşturmanın hem daha fazla bellek kullandığını hem de kaldırmayı imkânsız kıldığını gösterir. Tek bir adlandırılmış fonksiyon kullanın ya da olay delegasyonu ile tek dinleyiciye indirin.
- capture değerini kaldırırken unutmak:
trueile eklenen dinleyicifalseile kaldırılamaz. - Pasif dinleyicide preventDefault beklemek: Belge düzeyindeki
touchmovevewheeldinleyicileri varsayılan olarak pasif olabilir; engelleme gerekiyorsapassive: falseyazın. - Dinleyici içinde ağır iş yapmak: Uzun süren dinleyiciler kullanıcı etkileşimini geciktirir. Bunun sayfa hızı ölçümlerine etkisi için Core Web Vitals yazısına bakın.
Sık Sorulan Sorular
addEventListener aynı fonksiyonu iki kez ekler mi?
Hayır. Aynı tür, aynı fonksiyon referansı ve aynı capture değeriyle ikinci çağrı yok sayılır. capture değeri farklıysa iki ayrı kayıt oluşur. Her seferinde yeni yazılan anonim fonksiyonlar ise farklı nesneler olduğu için hepsi eklenir.
Dinleyiciye nasıl parametre gönderirim?
Dinleyici yalnızca olay nesnesini alır. Ek veri için dinleyiciyi bir ok fonksiyonu ya da normal fonksiyonla sarıp içeriden asıl fonksiyonu istediğiniz argümanlarla çağırırsınız veya dış kapsamdaki bir değişkeni kullanırsınız. Kaldırma gerekecekse bu sarmalayıcıyı bir değişkende saklayın ya da signal kullanın.
Dinleyicinin içinden başka bir dinleyici eklersem hemen çalışır mı?
MDN'ye göre bir olay işlenirken aynı hedefe eklenen yeni dinleyici o olayı almaz; ancak olay akışının daha sonraki bir aşamasında, örneğin kabarcıklanma evresinde başka bir öğede tetiklenebilir.
EventTarget.when() nedir, addEventListener yerine kullanılmalı mı?
when(), olay akışını bir Observable olarak döndüren yeni bir yöntemdir ve subscribe() ile kullanılır. MDN basit bir sayaç örneğinde ikisini neredeyse eşdeğer gösterir; farkı, olay akışlarını birleştirip dönüştürebilmenizdir. Tarayıcı desteği için MDN uyumluluk tablosuna bakın; yaygın kullanım için addEventListener() temel yöntem olmaya devam eder.
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: Web API öğrenme rehberi · Event bubbling, capturing ve delegation · CustomEvent ve EventTarget · Klavye olayları · Pointer events · Form gönderme ve FormData · JavaScript event loop