Array kosong benar tetapi mereka juga sama dengan false.
var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");
Saya kira ini karena konversi implisit yang dioperasikan oleh operator kesetaraan.
Adakah yang bisa menjelaskan apa yang terjadi di balik layar?
javascript
Patonza
sumber
sumber
arr == true
tidak mengevaluasi benar ;-)===
. Kemudian jika Anda ingin menguji kekosongan array, gunakanarr === []
arr === []
, karena itu SELALU akan mengembalikan false, karena sisi kanan adalah instantiating array baru, dan variabel di sebelah kiri tidak dapat merujuk ke sesuatu yang baru saja Anda buat. Menguji kekosongan harus dilakukan dengan melihat ke atasarr.length === 0
.Jawaban:
Anda menguji berbagai hal di sini.
if (arr)
dipanggil objek (Array adalah instance dari Objek di JS) akan memeriksa apakah objek tersebut ada, dan mengembalikan true / false.Ketika Anda menelepon
if (arr == false)
Anda membandingkan nilai objek ini dan nilai primitiffalse
. Secara internal,arr.toString()
disebut, yang mengembalikan string kosong""
.Ini karena
toString
dipanggil pada pengembalian ArrayArray.join()
, dan string kosong adalah salah satu nilai salah dalam JavaScript.sumber
Boolean([])
kembalitrue
?Mengenai garis:
Mungkin ini akan membantu:
Apa yang saya yakini sedang terjadi adalah bahwa boolean
false
dipaksa0
untuk dibandingkan dengan objek (sisi kiri). Objek dipaksa ke string (string kosong). Kemudian, string kosong dipaksa menjadi angka, juga, yaitu nol. Dan perbandingan terakhirnya adalah0
==0
, yaitutrue
.Sunting: Lihat bagian spesifikasi ini untuk detail tentang cara kerjanya.
Inilah yang terjadi, mulai dari aturan # 1:
Aturan selanjutnya yang berlaku adalah # 19:
Hasilnya
ToNumber(false)
adalah0
, jadi sekarang kita memiliki:Sekali lagi, aturan # 1 memberitahu kita untuk melompat ke langkah # 14, tetapi langkah selanjutnya yang benar-benar berlaku adalah # 21:
Hasilnya
ToPrimitive([])
adalah string kosong, jadi kita sekarang memiliki:Sekali lagi, aturan # 1 memberitahu kita untuk melompat ke langkah # 14, tetapi langkah selanjutnya yang benar-benar berlaku adalah # 17:
Hasilnya
ToNumber("")
adalah0
, yang meninggalkan kita dengan:Sekarang, kedua nilai memiliki tipe yang sama, jadi langkah-langkahnya berlanjut dari # 1 hingga # 7, yang mengatakan:
Jadi kita kembali
true
.Secara singkat:
sumber
[] == 0
benar. Saya mengerti bagaimana hal ini terjadi berdasarkan penjelasan Anda tentang spec, tetapi sepertinya perilaku bahasa yang aneh dari sudut pandang logis.Untuk melengkapi jawaban Wayne dan mencoba menjelaskan mengapa
ToPrimitive([])
kembali""
, ada baiknya mempertimbangkan dua jenis jawaban yang mungkin untuk pertanyaan 'mengapa'. Jenis jawaban pertama adalah: "karena spesifikasi mengatakan ini adalah bagaimana JavaScript akan berperilaku." Dalam spec ES5, bagian 9.1 , yang menjelaskan hasil ToPrimitive sebagai nilai default untuk Objek:Bagian 8.12.8 menjelaskan
[[DefaultValue]]
metode ini. Metode ini menggunakan "petunjuk" sebagai argumen, dan petunjuk itu bisa berupa String atau Angka. Untuk menyederhanakan masalah dengan mengeluarkan beberapa detail, jika petunjuknya adalah String, maka[[DefaultValue]]
mengembalikan nilaitoString()
jika ada dan mengembalikan nilai primitif dan sebaliknya mengembalikan nilaivalueOf()
. Jika petunjuknya adalah Angka, prioritastoString()
danvalueOf()
dibalik sehinggavalueOf()
disebut pertama dan nilainya dikembalikan jika itu primitif. Jadi, apakah[[DefaultValue]]
mengembalikan hasiltoString()
atauvalueOf()
tergantung pada PreferredType yang ditentukan untuk objek dan apakah fungsi-fungsi ini mengembalikan nilai primitif.valueOf()
Metode Obyek default hanya mengembalikan objek itu sendiri, yang berarti bahwa kecuali kelas menimpa metode default,valueOf()
hanya mengembalikan Objek itu sendiri. Ini adalah kasus untukArray
.[].valueOf()
mengembalikan objek[]
itu sendiri. Karena suatuArray
objek bukan primitif,[[DefaultValue]]
petunjuknya tidak relevan: nilai kembali untuk array akan menjadi nilaitoString()
.Mengutip JavaScript David Flanagan : The Definitive Guide , yang merupakan buku luar biasa yang harus menjadi tempat pertama setiap orang untuk mendapatkan jawaban atas pertanyaan-pertanyaan ini:
Jenis jawaban kedua untuk pertanyaan "mengapa", selain "karena spesifikasi mengatakan", memberikan beberapa penjelasan mengapa perilaku tersebut masuk akal dari perspektif desain. Pada masalah ini saya hanya bisa berspekulasi. Pertama, bagaimana seseorang mengonversi array menjadi angka? Satu-satunya kemungkinan yang masuk akal yang dapat saya pikirkan adalah untuk mengubah array kosong menjadi 0 dan array non-kosong menjadi 1. Tetapi seperti yang diungkapkan oleh Wayne, array kosong akan dikonversi ke 0 untuk banyak jenis perbandingan. Di luar ini, sulit untuk memikirkan nilai pengembalian primitif yang masuk akal untuk Array.valueOf (). Jadi orang dapat berargumen bahwa lebih masuk akal untuk
Array.valueOf()
menjadi default dan mengembalikan Array itu sendiri, yang mengarahtoString()
ke hasil yang digunakan oleh ToPrimitive. Lebih masuk akal untuk mengubah Array menjadi string, daripada angka.Selain itu, seperti yang ditunjukkan oleh kutipan Flanagan, keputusan desain ini memang memungkinkan jenis perilaku menguntungkan tertentu. Misalnya:
Perilaku ini memungkinkan Anda untuk membandingkan array elemen tunggal dengan angka dan mendapatkan hasil yang diharapkan.
sumber
sumber
Di if (arr), selalu dievaluasi (ToBoolean) menjadi true jika arr adalah objek karena semua objek dalam JavaScript benar . (null bukan objek!)
[] == false
dievaluasi dalam pendekatan iteratif. Pada awalnya, jika satu sisi==
adalah primitif dan yang lainnya adalah objek, ia mengubah objek menjadi primitif pada awalnya, kemudian mengubah kedua sisi menjadi Angka jika kedua sisi tidakstring
(perbandingan string digunakan jika kedua sisi adalah string). Jadi perbandingannya adalah iterasi seperti,[] == false
->'' == false
->0 == 0
->true
.sumber
Contoh:
Itu terjadi karena
[]
adalahArray
objek kosong →ToPrimitive([])
→ "" →ToNumber("")
→0
ToNumber(false)
→ 0sumber
Array dengan elemen (terlepas dari apakah 0, false atau array kosong lainnya), selalu memutuskan untuk
true
menggunakan Perbandingan Kesetaraan Abstrak==
.Tetapi menggunakan Pembandingan Kesetaraan Ketat
===
, Anda mencoba untuk mengevaluasi konten variabel serta tipe datanya, itulah sebabnya:sumber
Anda dapat mengosongkan Array JavaScript dengan mereferensikannya ke array baru, menggunakan
list = []
atau menghapus elemen-elemen dari array yang saat ini direferensikanlist.length = 0
.Sumber: Array Kosong JavaScript
sumber
Tidak satu pun di atas membantu saya, ketika mencoba menggunakan plugin pemetaan knockout.js, mungkin karena "array kosong" tidak benar-benar kosong.
Saya akhirnya menggunakan:
data-bind="if: arr().length"
yang melakukan trik.Ini khusus untuk sistem gugur, bukan pertanyaan OP, tapi mungkin itu akan membantu orang lain menjelajah di sini dalam situasi yang sama.
sumber