Operatörler: İfadelerin İşini Yapan Yapı Taşları
JavaScript'te yazdığınız önemsiz sayılmayacak her satır aslında operatörlerden oluşur — bir ya da iki değer alıp yenisini üreten sembollerden yani. + toplar, === karşılaştırır, && boolean değerleri birleştirir, ? : ikisinden birini seçer. Çoğu başka dillerden tanıdık gelecek; ama baştan bilmekte fayda olan JavaScript'e özgü birkaç cilve de var.
Hepsini kategori kategori ele alacağız; en sona da en az kullanacağınız ama gerektiğinde kurtarıcı olan operatörleri bırakacağız.
JavaScript Aritmetik Operatörler
Temel olanlar tam beklediğiniz gibi davranır:
Şunlara dikkat etmekte fayda var:
/her zaman kayan noktalı bölme yapar. Yani7 / 2sonucu3değil,3.5'tir. Tam sayı istiyorsanMath.floor(7 / 2)veyaMath.trunc(7 / 2)kullanman gerekir.%aslında matematiksel anlamda modülo değil, kalan operatörüdür. İşaretini soldaki operanddan alır:-7 % 3sonucu-1değil,-1'dir.+operatörü aşırı yüklenmiştir (overloaded). Taraflardan biri string ise toplama yerine birleştirme (concatenation) yapar:"3" + 1sonucu"31"olur. Buna birazdan daha ayrıntılı değineceğiz.
Artırma ve azaltma operatörleri
count++ ile ++count arasındaki fark yalnızca ifadenin değerini aynı satırda kullandığınızda öne çıkar. Tek başına bir deyim olarak ikisi de aynı işi yapar. Çoğu stil rehberi, daha okunaklı olduğu için count += 1 kullanmanızı önerir.
+ Operatörünün İki Farklı Yüzü
Bu konu herkesi en az bir kez tökezletir:
Operandlardan biri string ise + artık toplama değil, string birleştirme operatörüne dönüşür ve diğer tarafı da stringe çevirir. Geri kalan tüm aritmetik operatörler tam tersini yapar: stringleri sayıya çevirir:
Özet: string oluştururken template literal kullanmayı tercih edin (`price: ${5}`). Matematik yaparken de girdilerinizin gerçekten sayı olduğundan emin olun — Number(x) veya parseInt(x, 10) ile açık açık dönüşüm yapabilirsiniz.
JavaScript Karşılaştırma Operatörleri
Karşılaştırma operatörleri boolean döner. İki türü var: sıkı (strict) ve gevşek (loose).
=== ve !== operatörleri katı karşılaştırma yapar — hem değer hem de tip aynı olmalıdır. == ve != ise karşılaştırma yapmadan önce tipleri dönüştürür; bu da null == undefined sonucunun true çıkması ya da [] == false ifadesinin true olması gibi sürprizlere yol açar. Varsayılan olarak === ve !== kullanın. Yaygın olan tek istisna x == null kalıbıdır; bu da "x değeri null veya undefined mi?" sorusunu sormanın pratik bir kısayoludur.
Sıralama operatörleri sayılarda beklediğiniz gibi, string'lerde ise alfabetik olarak çalışır:
String karşılaştırması karakter kodlarına göre yapıldığı için büyük/küçük harfe duyarlıdır. Daha insana yakın bir sıralama istiyorsan String.prototype.localeCompare metodunu kullan.
Mantıksal Operatörler
&& (VE), || (VEYA) ve ! (DEĞİL) operatörleri boolean değerleri birleştirir — ama saf boolean cebrinin ima ettiğinden çok daha fazlasını yapabilirler.
Ama ufak bir sürpriz var: && ve || aslında true ya da false döndürmez. Bu operatörler, operandlarından birini döndürür. && karşılaştığı ilk falsy değeri verir; hepsi truthy ise sonuncusunu döndürür. || ise ilk truthy değeri; hepsi falsy ise sonuncu değeri döndürür.
Bu yüzden sık sık const displayName = user.name || "Guest" gibi kalıplar görürsün — boş olmayan ilk değeri al mantığı. Kısa ve pratik ama dikkat: || operatörü 0, "" ve false değerlerini de "boş" sayıp yedeğe düşer. Eğer bunlar senin için geçerli değerlerse, onun yerine ?? (nullish coalescing) kullan (aşağıda anlatıyorum).
Her iki operatör de kısa devre (short-circuit) yapar: sol taraf sonucu zaten belirliyorsa, sağ taraf hiç çalıştırılmaz.
Nullish Coalescing Operatörü ??
?? aslında || ile benzer iş yapar ama sadece null veya undefined değerlerinde devreye girer; 0, "" ya da false gibi değerlerde tetiklenmez.
?? operatörünü, geçerli bir değerin falsy olabileceği yerlerde kullan — sayaçlar, boş string'ler, bilinçli konulmuş false gibi. || ise "hangi falsy değer olursa olsun eksik sayılsın" dediğin durumlar için uygundur. Modern kodda, null olmayan varsayılan değerler atamak istediğin opsiyonel durumlar için ?? çok daha güvenli bir tercih.
Atama Operatörleri
javascript atama operatörleri içinde en temel olan =, bir değer atar. Bileşik formlar ise atamayı başka bir operatörle birleştirir:
||=, &&= ve ??= gibi mantıksal atama operatörleri de var. Bunlar, yalnızca mevcut değer belirli bir koşulu sağladığında atama yapar:
if bloklarıyla uğraşmadan varsayılan değer atamak istediğimizde bunlar çok işe yarıyor.
Ternary Operatörü (Üçlü Operatör)
condition ? a : b yazımı, if/else yapısının ifade (expression) biçimidir. Koşul truthy ise a, aksi halde b değerini döndürür:
Ternary ifade, kısa değer seçimlerinde harika iş görür. Ama iç içe geçmeye başladığı anda okunaksız hale gelir — kendini a ? b : c ? d : e gibi bir şey yazarken bulursan, onun yerine if/else ya da bir lookup nesnesi kullan.
typeof ve instanceof
typeof, operandının tipini anlatan bir string döndürür:
Aklınızda tutmanız gereken iki tuhaflık var: typeof null sonucu "object" döner (1995'ten kalma, artık kalıcılaşmış bir hata) ve diziler de "object" olarak görünür. Diziler için Array.isArray(x), null kontrolü için ise x === null kullanın.
instanceof ise bir nesnenin belirli bir constructor'dan türetilip türetilmediğini kontrol eder:
Spread ve Rest Aynı ... İşaretini Kullanır
... işaretini iki farklı yerde görürsün. Spread olarak kullanıldığında, bir iterable'ı tek tek elemanlara açar:
Rest olarak kullanıldığında ise birden fazla değeri tek bir dizide toplar. Bunu genelde fonksiyon parametrelerinde ya da destructuring sırasında görürüz:
Aynı syntax, zıt görevler. Spread açar, rest ise toplar. Hangisinin hangisi olduğunu bağlam belirler: bir fonksiyon çağrısında veya literal içinde kullanıldığında açar; parametre listesinde veya destructuring deseninde ise toplar.
Operatör Önceliği (Kafan Karışırsa Parantez Kullan)
JavaScript'te operatörlerin bir önceliği vardır ve birden fazla operatörü bir arada kullandığında hangisinin önce çalışacağını bu öncelik belirler. Çarpma toplamadan, karşılaştırma mantıksal operatörlerden önce gelir, vs:
Tam liste uzun ve kimse hepsini ezbere bilmez. Basit bir alışkanlık vakaların %99'unu kurtarır: operatörleri karıştırdığınızda ve sıralamadan emin değilseniz, parantez ekleyin. Kod hem daha okunur olur hem de okuyanın hafızasına bağlı kalmaz.
Bit Düzeyinde Operatörler (Genelde Aradığınız Şey Değildir)
Eksik kalmasın diye söyleyelim: &, |, ^, ~, <<, >> ve >>> operatörleri tamsayıların ikili (binary) gösterimi üzerinde çalışır. Bunları daha çok grafik kodlarında, düşük seviyeli protokollerde ve arada bir karşınıza çıkan flag-bitmask API'lerinde görürsünüz.
Sık görülen ama pek önerilmeyen bir numara: n | 0 bir sayıyı 32-bit tam sayıya indirger. Eskiden bu yöntem, Math.trunc'un daha hızlı bir alternatifi olarak kullanılırdı. Ama yapmayın — Math.trunc hem daha okunaklı hem de 32-bit aralığının dışındaki sayılarda da düzgün çalışır.
Sırada: if/else
Operatörler değer üretir; if/else ise bu değerlere bakıp hangi kod dalının çalışacağına karar verir. Yukarıda gördüğümüz karşılaştırma ve mantıksal operatörlerle yapacağınız şeylerin büyük kısmı, sonuçlarını koşullu ifadelere beslemek olacak — bir sonraki sayfanın konusu da tam olarak bu.
Sıkça Sorulan Sorular
JavaScript'teki temel operatörler nelerdir?
JavaScript'te aritmetik (+, -, *, /, %, **), karşılaştırma (===, !==, <, >), mantıksal (&&, ||, !) ve atama (=, +=, -=) operatörleri var. Bir de ternary ? :, typeof ve nullish coalescing ?? gibi özel olanlar mevcut. Kısacası ifadelerin ve kontrol akışının yapı taşları bunlar.
JavaScript'te == ile === arasındaki fark nedir?
=== hem değeri hem de tipi kontrol eder. == ise karşılaştırma yapmadan önce tip dönüşümü uyguladığı için 0 == "0" sonucu true ama 0 === "0" sonucu false olur. Varsayılan olarak === kullanın — =='nin tip dönüştürme kuralları öyle ince ki, code review'da bile gözden kaçacak bug'lara yol açar.
JavaScript'te ternary operatörü ne işe yarar?
condition ? a : b aslında tek satırlık bir if/else'tir ve bir değer döndürür. condition truthy ise a, değilse b değerlendirilir. const label = count === 1 ? 'item' : 'items' gibi kısa koşullu ifadelerde çok kullanışlıdır, ama iç içe ternary yazmaya başlayınca okunabilirlik hızla düşer.
|| yerine ne zaman ?? kullanmalıyım?
|| operatörü tüm falsy değerlerde — yani 0, "" ve false dahil — fallback'e düşer. ?? ise sadece null veya undefined geldiğinde devreye girer. Mesela count ?? 10 yazdığınızda geçerli bir 0 değerini korumak istiyorsanız ?? kullanın. Herhangi bir falsy değerin fallback'i tetiklemesini gerçekten istiyorsanız, || işinizi görür.