JavaScript'te === (katı eşitlik) iki değeri tip dönüşümü yapmadan karşılaştırır; tipler farklıysa sonuç false olur. == (gevşek eşitlik) ise önce tipleri dönüştürüp sonra karşılaştırır, bu yüzden "1" == 1 doğrudur. Object.is() neredeyse === gibi çalışır, ancak NaN değerini kendisine eşit sayar ve +0 ile -0 değerlerini ayırt eder. Günlük kodda varsayılan seçim === olmalıdır.
Bu yazıda üç karşılaştırma yöntemini ve dilin içinde kullanılan dördüncü algoritma olan SameValueZero'yu, NaN ve -0 gibi köşe durumlarla birlikte inceliyoruz.
Dört eşitlik algoritması

ECMAScript spesifikasyonu dört ayrı eşitlik algoritması tanımlar. Üçüne doğrudan operatör veya metotla ulaşırsınız; dördüncüsü bazı yerleşik metotların içinde çalışır.
| Algoritma | Kullanıldığı yer | Tip dönüşümü | NaN ile NaN | +0 ile -0 |
|---|---|---|---|---|
| IsLooselyEqual | == | var | false | true |
| IsStrictlyEqual | ===, indexOf, lastIndexOf, switch case | yok | false | true |
| SameValue | Object.is() | yok | true | false |
| SameValueZero | includes, Map ve Set anahtarları | yok | true | true |
Hiçbiri nesnelerin yapısını karşılaştırmaz. Aynı özelliklere sahip iki ayrı nesne dört algoritmaya göre de eşit değildir.
Katı eşitlik: ===
=== operatöründe hiçbir değer dönüştürülmez. Tipler farklıysa sonuç false, tipler aynıysa değerler karşılaştırılır. Sayılarda iki istisna vardır: NaN hiçbir değere, kendisine bile eşit değildir; +0 ile -0 ise eşit kabul edilir. Nesnelerde yalnızca aynı nesneye başvuruluyorsa sonuç true olur.
console.log(1 === 1); // true
console.log(1 === "1"); // false
console.log(null === undefined); // false
console.log(NaN === NaN); // false
console.log(+0 === -0); // true
const o = {};
console.log(o === o); // true
console.log({} === {}); // falseGevşek eşitlik: == nasıl çalışır?
== simetriktir; a == b ile b == a her zaman aynı sonucu verir. Spesifikasyondaki adımları sadeleştirirsek işleyiş şöyledir:
- Tipler aynıysa
===ile aynı karşılaştırma yapılır. - Taraflardan biri
nullveyaundefinedise diğeri denullya daundefinedolmadıkça sonuçfalseolur. - Bir taraf nesne, diğeri ilkel değerse nesne ilkel değere dönüştürülür.
- Boolean taraf sayıya çevrilir:
true1,false0 olur. - Sayı ile metin karşılaştırılırken metin sayıya çevrilir; çeviri başarısızsa
NaNçıkar ve sonuçfalseolur. - Symbol ile Symbol olmayan bir değer hiçbir zaman eşit değildir; BigInt ile Number matematiksel değerlerine göre karşılaştırılır.
console.log("1" == 1); // true
console.log(0 == ""); // true
console.log(0 == false); // true
console.log("" == false); // true
console.log([1, 2] == "1,2"); // true
console.log(0n == 0); // true
console.log(null == undefined); // true
console.log(null == 0); // false
console.log(null == false); // false
console.log(undefined == false); // falseSon üç satır şaşırtıcı gelebilir: null ve undefined koşullarda yanlış (falsy) sayılır, ama == ile yalnızca birbirlerine eşittirler. Koşullarda doğru veya yanlış sayılma ile == false sonucu aynı şey değildir; bu konunun ayrıntıları tip dönüşümü yazısında.
NaN: kendisine eşit olmayan değer

NaN, sonucu sayı olarak ifade edilemeyen işlemlerden çıkar (örneğin 0 / 0 veya Number("abc")). === ve == açısından NaN hiçbir şeye eşit değildir; x !== x ifadesinin doğru olduğu tek durum x değerinin NaN olmasıdır. Kontrol için Number.isNaN() kullanın.
Bu durum dizilerde arama yaparken farkı ortaya çıkarır: indexOf() katı eşitlik kullandığı için NaN bulamaz, includes() ise SameValueZero kullandığı için bulur. switch ifadesindeki case NaN dalı da hiçbir zaman eşleşmez.
const x = Number("abc");
console.log(x); // NaN
console.log(x === x); // false
console.log(Number.isNaN(x)); // true
const dizi = [1, NaN, 3];
console.log(dizi.indexOf(NaN)); // -1
console.log(dizi.includes(NaN)); // true
switch (NaN) {
case NaN:
console.log("eşleşti"); // hiçbir şey yazılmaz
}+0 ve -0
Number tipinde sıfırın iki gösterimi vardır. Günlük işlemlerde fark edilmezler ve === ile eşittirler. Farkı en kolay sıfıra bölmede görürsünüz. Negatif sıfır, sıfır olan bir değerin işaretini çevirdiğinizde veya Math.round(), Math.min() gibi bazı metotların sonucunda ortaya çıkabilir.
console.log(42 / +0); // Infinity
console.log(42 / -0); // -Infinity
console.log(-0 === 0); // true
console.log(Object.is(-0, 0)); // false
console.log(Object.is(Math.min(-0, +0), -0)); // true
const hiz = 0;
const ters = -hiz;
console.log(Object.is(ters, -0)); // trueObject.is(): SameValue
Object.is() tip dönüşümü yapmaz ve sayılardaki iki istisnayı kaldırır: NaN kendisine eşittir, +0 ile -0 farklıdır. Dil, bir değerin "aynı kimliğe" sahip olup olmadığını kontrol etmesi gereken pek çok yerde bu algoritmayı kullanır. Örneğin değiştirilemez bir özelliği Object.defineProperty() ile yeniden tanımlarken yeni değer eskisiyle SameValue algoritmasına göre karşılaştırılır.
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(0, -0)); // false
console.log(Object.is("a", "a")); // true
console.log(Object.is({}, {})); // falseMDN'in önerisi açıktır: işaretli sıfırları ayırt etmeniz gerekmiyorsa Object.is() yerine === kullanın. Yalnızca NaN karşılaştırması gerekiyorsa Number.isNaN() ile özel kontrol yapmak çoğu zaman daha anlaşılırdır.
SameValueZero: includes, Map ve Set
SameValueZero, SameValue ile aynıdır; tek farkı +0 ve -0 değerlerini eşit saymasıdır. Doğrudan bir JavaScript API'si olarak sunulmaz, ama Array.prototype.includes(), TypedArray'lerin includes() metodu ve Map ile Set anahtar karşılaştırmaları bu algoritmayı kullanır. Bu yüzden NaN bir Map anahtarı olarak sorunsuz çalışır.
const m = new Map();
m.set(NaN, "bulundu");
console.log(m.get(NaN)); // bulundu
const s = new Set([0, -0, NaN, NaN]);
console.log(s.size); // 2
function sameValueZero(x, y) {
if (typeof x === "number" && typeof y === "number") {
return x === y || (x !== x && y !== y);
}
return x === y;
}
console.log(sameValueZero(NaN, NaN), sameValueZero(0, -0)); // true trueMap ve Set'in diğer özellikleri için Map, Set ve WeakMap yazısına bakabilirsiniz.
Karşılaştırma tablosu

| x | y | == | === | Object.is | SameValueZero |
|---|---|---|---|---|---|
| +0 | -0 | true | true | false | true |
| NaN | NaN | false | false | true | true |
| 0 | false | true | false | false | false |
| "" | 0 | true | false | false | false |
| "17" | 17 | true | false | false | false |
| [1, 2] | "1,2" | true | false | false | false |
| null | undefined | true | false | false | false |
| null | false | false | false | false | false |
| { a: 1 } | { a: 1 } | false | false | false | false |
Nesneleri içerik bakımından karşılaştırmak
JavaScript genel amaçlı bir derin eşitlik (deep equality) operatörü sunmaz. İki nesnenin aynı özelliklere sahip olup olmadığını öğrenmek istiyorsanız özellikleri kendiniz karşılaştıran bir fonksiyon yazmanız ya da bir kütüphanenin veya çalışma ortamının sunduğu yardımcıyı kullanmanız gerekir. Basit, düz nesneler için aşağıdaki gibi bir fonksiyon iş görür; iç içe nesneler, diziler ve özel tipler için daha kapsamlı bir çözüm gerekir.
function duzEsit(a, b) {
const ka = Object.keys(a);
const kb = Object.keys(b);
if (ka.length !== kb.length) return false;
return ka.every((k) => Object.hasOwn(b, k) && Object.is(a[k], b[k]));
}
console.log(duzEsit({ x: 1, y: 2 }, { y: 2, x: 1 })); // true
console.log(duzEsit({ x: 1 }, { x: "1" })); // falseHangi karşılaştırmayı ne zaman kullanmalı?
===: varsayılan seçim. Tip dönüşümü yapmadığı için sonucu tahmin etmek kolaydır.==: yalnızca ekibinizin bilinçli olarak benimsediğideger == nullgibi dar kalıplarda.Object.is():-0ile+0ayrımının gerçekten önemli olduğu durumlarda; örneğin özellik tanımlayıcılarıyla çalışan meta programlama kodunda.Number.isNaN()veincludes():NaNaramanız veya kontrol etmeniz gerektiğinde.
Bu ayrımı yapmanın pratik bir faydası da vardır: kod incelemesinde == veya Object.is() gördüğünüzde, yazarın bilinçli bir tercih yaptığını ve özel bir durumu ele aldığını anlarsınız.
Sık yapılan hatalar
- Kullanıcı girdisini
==ile sayıyla karşılaştırmak:"" == 0doğru olduğu için boş girdi sıfır gibi görünür. Girdiyi önce açıkçaNumber()ile çevirip===kullanın. deger === NaNyazmak: her zamanfalseverir.Number.isNaN(deger)kullanın.indexOf(NaN)ile arama: sonuç her zaman -1'dir;includes()veyafindIndex(Number.isNaN)kullanın.- Global
isNaN()ileNumber.isNaN()farkını gözden kaçırmak: global olan önce argümanı sayıya çevirir, bu yüzdenisNaN("abc")doğru döner.Number.isNaN()dönüşüm yapmaz. - Nesneleri
===ile içerik bakımından karşılaştırmak: yalnızca kimlik karşılaştırılır.
Sık Sorulan Sorular
== mi === mi kullanmalıyım?
Neredeyse her durumda ===. Sonucu tahmin etmek kolaydır ve tip dönüşümü olmadığı için gizli hatalara yol açmaz. == yalnızca deger == null gibi ekibin bilinçli olarak benimsediği kalıplarda tercih edilebilir.
Object.is() ile === arasındaki fark nedir?
Yalnızca iki noktada ayrılırlar: Object.is(NaN, NaN) doğru, NaN === NaN yanlıştır; Object.is(0, -0) yanlış, 0 === -0 doğrudur. Diğer tüm değerlerde aynı sonucu verirler.
Neden [] == false doğru çıkıyor?
Boş dizi önce ilkel değere çevrilir ve "" olur. Boolean taraf sayıya, yani 0'a çevrilir; ardından "" da sayıya çevrilip 0 olur. Sonuç 0 == 0, yani true. Buna rağmen boş dizi bir koşulda doğru (truthy) sayılır.
İki diziyi nasıl karşılaştırırım?
=== yalnızca aynı dizi mi diye bakar. Eleman eleman karşılaştırmak için uzunlukları kontrol edip every() ile her indeksi karşılaştırabilirsiniz. Dizi metotları için map, filter, reduce yazısına bakın.
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 · Tip dönüşümü · JavaScript veri tipleri · Number ve BigInt · Map, Set ve WeakMap