Sebagai ahli matematika profesional, saya melihat dalam operator kesamaan Javscript ==
(juga disebut "perbandingan abstrak", "kesetaraan longgar" ) upaya untuk membangun hubungan ekivalensi antara entitas, yang termasuk menjadi refleksif , simetris , dan transitif . Sayangnya, dua dari tiga sifat dasar ini gagal:
A == A
mungkin salah, mis
NaN == NaN // false
A == B
dan B == C
bersama-sama tidak menyiratkan A == C
, mis
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
A == B
menyiratkan B == A
, pelanggaran mana yang mungkin tidak terpikirkan dalam kasus apa pun dan akan menyebabkan pemberontakan yang serius;)
Mengapa hubungan kesetaraan penting?
Karena itulah jenis hubungan yang paling penting dan lazim, didukung oleh banyak contoh dan aplikasi. Aplikasi yang paling penting adalah dekomposisi entitas menjadi kelas kesetaraan , yang dengan sendirinya merupakan cara yang sangat mudah dan intuitif untuk memahami hubungan. Dan kegagalan untuk menjadi ekuivalensi mengarah pada kurangnya kelas ekivalensi, yang pada gilirannya mengarah pada kurangnya intuisi dan kompleksitas yang tidak perlu yang terkenal.
Mengapa ini merupakan ide yang mengerikan untuk menulis ==
untuk hubungan yang tidak setara?
Karena itu merusak keakraban dan intuisi kita, karena secara harfiah ada hubungan yang menarik dari kesamaan, kesetaraan, kongruensi, isomorfisme, identitas dll adalah kesetaraan.
Jenis konversi
Alih-alih mengandalkan kesetaraan intuitif, JavaScript memperkenalkan konversi jenis:
Operator kesetaraan mengubah operan jika tidak dari jenis yang sama, kemudian menerapkan perbandingan yang ketat.
Tetapi bagaimana definisi jenis konversi? Melalui serangkaian aturan rumit dengan banyak pengecualian?
Mencoba membangun relasi kesetaraan
Boolean. Jelas true
dan false
tidak sama dan harus di kelas yang berbeda.
Angka Untungnya, kesetaraan angka sudah didefinisikan dengan baik, di mana dua angka yang berbeda tidak pernah berada dalam kelas ekivalensi yang sama. Dalam matematika, itu. Dalam JavaScript gagasan angka agak berubah bentuk melalui kehadiran yang lebih eksotis -0
, Infinity
dan -Infinity
. Intuisi matematika kami menyatakan bahwa 0
dan -0
harus di kelas yang sama (pada kenyataannya -0 === 0
adalah true
), sedangkan masing-masing infinities adalah kelas terpisah.
Bilangan dan Boolean. Mengingat nomor kelas, di mana kita meletakkan boolean? false
menjadi mirip dengan 0
, sedangkan true
menjadi serupa 1
tetapi tidak ada nomor lain:
true == 1 // true
true == 2 // false
Apakah ada logika di sini untuk true
disatukan 1
? Diakui 1
dibedakan, tetapi begitu juga -1
. Saya pribadi tidak melihat alasan untuk mengkonversi true
ke 1
.
Dan itu menjadi lebih buruk:
true + 2 // 3
true - 1 // 0
Jadi true
memang diubah menjadi di 1
antara semua angka! Apakah ini logis? Apakah ini intuitif? Jawabannya dibiarkan sebagai latihan;)
Tapi bagaimana dengan ini:
1 && true // true
2 && true // true
Satu-satunya boolean x
dengan x && true
makhluk true
adalah x = true
. Yang membuktikan bahwa keduanya 1
dan 2
(dan nomor lain selain 0
) berkonversi ke true
! Apa yang ditunjukkannya adalah bahwa konversi kami gagal dalam properti penting lainnya - yaitu penambangan . Berarti bahwa dua entitas yang berbeda dapat dikonversi ke entitas yang sama. Yang dengan sendirinya tidak harus menjadi masalah besar. Masalah besar muncul ketika kita menggunakan konversi ini untuk menggambarkan hubungan "kesamaan" atau "kesetaraan longgar" dari apa pun yang kita ingin menyebutnya. Tapi satu hal yang jelas - itu tidak akan menjadi hubungan ekivalensi dan tidak akan dijelaskan secara intuitif melalui kelas ekivalensi.
Tetapi bisakah kita melakukan yang lebih baik?
Setidaknya secara matematis - pasti ya! Hubungan kesetaraan sederhana antara boolean dan angka hanya dapat dibangun dengan false
dan 0
berada di kelas yang sama. Jadi false == 0
akan menjadi satu-satunya kesetaraan longgar non-sepele.
Bagaimana dengan string?
Kita dapat memangkas string dari spasi putih di awal dan akhir untuk mengkonversi ke angka, juga kita bisa mengabaikan nol di depan:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Jadi kita mendapatkan aturan sederhana untuk string - trim spasi putih dan nol di depan. Entah kita mendapatkan angka atau string kosong, dalam hal ini kita mengkonversi ke angka itu atau nol. Atau kami tidak mendapatkan nomor, dalam hal ini kami tidak mengonversi sehingga tidak ada hubungan baru.
Dengan cara ini kita benar-benar bisa mendapatkan hubungan kesetaraan yang sempurna pada set boolean, angka, dan string! Kecuali itu ... Desainer JavaScript jelas memiliki pendapat lain:
' ' == '' // false
Jadi dua string yang keduanya dikonversi menjadi 0
tiba-tiba tidak serupa! Kenapa atau mengapa? Menurut aturan, string secara longgar sama persis ketika mereka benar-benar sama! Tidak hanya aturan ini memecah transitivitas seperti yang kita lihat, tetapi juga berlebihan! Apa gunanya membuat operator lain ==
agar benar-benar identik dengan yang lain ===
?
Kesimpulan
Operator kesetaraan longgar ==
bisa sangat berguna jika mematuhi beberapa hukum matematika dasar. Tapi sayangnya tidak ada manfaatnya.