Aynı Özelliklere Sahip Objeler Neden Birbirine Eşit Değil?

Merhabalar.

Yanılmıyorsam üç gündür bu projemin bir bug fixe ihtiyacı vardı ve nihayet bugün sorunun kaynağına ulaştım.

Javascript’te aynı özelliklere sahip iki obje asla birbirine eşit olamazmış.
“Two distinct objects can have same properties, but they are never equal. Only comparing the same object with itself returns true.”
Mesela:

let array1 = [1, 2, 3];
let array2 = [1, 2, 3];

console.log(
`
 ${array1 == array2} // false
 ${array1 === array2} //false
 ${ [1, 2, 3] == [1, 2, 3] } // false
 ${ [1, 2, 3] === [1, 2, 3] } // false
 ${ {key: "value"} == {key: "value" } } // false
 ${ {key: "value"} === {key: "value"} } // false
`
)

Bu olayı biraz araştırdım ve bu durumu açıklayan cevaplar genellikle aynı özelliklere sahip iki objenin asla birbirine eşit olamayacağından, ancak obje kendisiyle karşılaştırılırsa true döneceğinden; objelerin bellekte farklı yerleri olduğundan vs. bahsetmiş.
Ben ise bu olayın sebebini ve teorik yönünü merak ediyorum.
Niye böyle bir şey var ?
Yukarıdaki kodların hepsi true döndürse daha mantıklı olmaz mıydı, bunun arkasındaki mantık nedir ?
Neden Python’daki gibi olamazdı ? ([1, 2, 3] == [1, 2, 3] # true)
Kısacası, neden ?

1 Beğeni

Cunku Javascript aceleyle ve cok basit problemleri cozmek icin tasarlandi.

Basit bir == kontrolu neden potansiyel olarak uzun sureler alacak, kb’larca hafiza kullanacak bir is yapsin ki?

Hem bunu istiyorsan fonksiyonunu yazabilirsin.

Bu arada objelerin ozellikleri disinda ownProperty’leri filan var, prototipleri var. Buradaki her durum icin mantikli bir cevap bulabiliyor musun? Aceleyle bulmak ister miydin?

Python’daki gibi olabilirdi.

3 Beğeni

Python’da da iki farklı nesne nitelikleri aynı olsa bile normalde birbirine eşit olmuyor.

>>> class Object: pass

>>> Object() == Object()
False
>>> 

Sınıfa __eq__ veya __ne__ metodları eklenerek == işlecinin işlevi değiştirilebilir, list dahil çoğu gömülü tip bunu yapıyor.

Javascript’in buradaki farkı eşitlik işlecinin işlevini değiştiremiyor olmamız sanırım.

2 Beğeni

Hocam konu ile alakası yok ama ek olarak şunu sorabilirmiyim ?
Ruby’de de objelerin id'leri birbirine eşit değilken, Symbol denilen yapıların id'leri nasıl birbirine eşit olabiliyor?

"a".object_id == "a".object_id #=> false
:a.object_id == :a.object_id #=> true

Neden olamasin ki?

Objelerin id’lerinin esit olmamasi baska seyin id’lerinin esit olmasini engellemez ki?

“Neden sembollerin id’leri esit oluyor” diye sorsaydin interning var herhalde derdim, semboller kod icinde constant gibi (hatta daha kullanisli bir sekilde) kullanildiklari icin objelerinin bir onemi yok, switch veya == gibi kontrollerde birbirlerine esit cikmalarinin cok onemi var derdim.

1 Beğeni

objeleri karşılaştırmak istiyorsan

JSON.stringify(object1) === JSON.stringify(object2)

şeklinde bakaiblirsin.

Ama…

> JSON.stringify(null) === JSON.stringify(-Infinity)
< true
2 Beğeni

Az önce fark ettim ben de :smiley:
Sorunu çözdüğümde String.toString() ile karşılaştırmayı yapmayı tercih etmiştim. Sanırım en uygunu bu.

o zaman

var s1 = JSON.stringify(null) 
var s1 =  JSON.stringify(-Infinity)

var result = (s1 === "null" || s2 ==="null") ? false : s1 === s2 ? true : false  

JSON.stringify({a: 1, b: 2}) == JSON.stringify({b: 2, a: 1})
false

Tam olarak neyin esitligine bakmak istiyorsaniz oturup yazacaksiniz. Testleriyle beraber.

1 Beğeni

objeler aynı kaynaktan geliyorsa bu kısım sorun çıkarmaz

Evet ama amac “ayni kaynaktan gelip gelmediklerini” bulmak degil, esit olup olmadiklarini bulmak degil miydi?

1 Beğeni

aynı kaynakten geliyorsa senin yaptığın gibi şeyler olmaz, ha farklı farklı yerlerden buluyorsan bu objeleri o zaman farklı olaiblir o zaman oturup teker teker bakarsın.

JSON.stringify’in siralama garantisi yoksa ayni objeyi paslasan bile benim yaptigim gibi seyler olabilir.

Ben de onu diyorum.

1 Beğeni

netscape tarayıcısında kullanılması için 10 gün gibi kısa bir sürede yapıldı diye bir şey okumuştum doğru mu acaba