Diutamakan operator dengan operator Javascript Ternary

116

Saya sepertinya tidak bisa membungkus kepala saya di sekitar bagian pertama dari kode ini (+ =) dalam kombinasi dengan operator terner.

h.className += h.className ? ' error' : 'error'

Cara kerja kode ini menurut saya adalah sebagai berikut:

h.className = h.className + h.className ? ' error' : 'error'

Tetapi itu tidak benar karena itu memberikan kesalahan pada konsol saya.

Jadi pertanyaan saya adalah bagaimana cara menginterpretasikan kode ini dengan benar?

Baijs
sumber

Jawaban:

141
h.className = h.className + (h.className ? ' error' : 'error')

Anda ingin operator bekerja h.className, lebih baik spesifik tentang itu.
Tentu saja, tidak boleh ada kerugian h.className += ' error', tetapi itu masalah lain.

Juga, perhatikan yang +lebih diutamakan daripada operator terner: JavaScript Operator Precedence

Kobi
sumber
3
Saya pikir perlu dicatat bahwa, meskipun tidak ada kerusakan yang dapat terjadi h.className += ' error', itu juga meninggalkan ruang kosong di awal string jika awalnya kosong. Saya percaya inti dari operasi terner adalah untuk menghasilkan string yang tampak bersih.
JMTyler
@JMTyler - Itulah yang saya tunjukkan - Jika semua dilakukan hanya untuk menjaga jarak dari awal, saya tidak sepadan. (casing tepi termasuk pemilih jQuery atau XPath yang tepat). Terima kasih.
Kobi
@Kobi +1 untuk peringatan prioritas operator saja!
Ed Chapel
129

Pikirkan seperti ini:

<variable> = <expression> ? <true clause> : <false clause>

Cara pernyataan dieksekusi pada dasarnya adalah sebagai berikut:

  1. Apakah <expression>dievaluasi sebagai benar, atau apakah dievaluasi sebagai salah?
  2. Jika <expression>dievaluasi ke true, maka nilai <true clause>ditetapkan ke <variable>, <false clause>diabaikan, dan pernyataan berikutnya dijalankan.
  3. Jika <expression>bernilai false, maka <true clause>diabaikan dan nilai <false clause>ditetapkan ke <variable>.

Hal penting untuk disadari dengan operator terner dalam bahasa ini dan bahasa lain adalah bahwa kode apa pun yang ada <expression>harus menghasilkan hasil boolean saat dievaluasi: benar atau salah.

Dalam kasus contoh Anda, ganti "ditugaskan ke" dalam penjelasan saya dengan "ditambahkan ke", atau serupa untuk aritmatika steno mana pun yang Anda gunakan, jika ada.

Wayne Koorts
sumber
Perhatikan apakah komentar yang sempurna sesuai :) Ini melewatkan penjelasan apa pun tentang mengapa ekspresi kiri "dikelompokkan bersama" terlebih dahulu (yaitu karena +memiliki prioritas yang lebih besar daripada operator kondisional / terner (sebenarnya operator kondisional hampir selalu yang terakhir) dievaluasi dalam ekspresi apa pun).
Gone Coding
10

Itu +=melakukan apa yang Anda inginkan, tetapi dalam pernyataan terner di sebelah kanannya, ia memeriksa apakah h.classNameitu salah, yang akan terjadi jika tidak ditentukan. Jika benar (yaitu jika nama kelas sudah ditentukan), maka kesalahan akan ditambahkan dengan spasi (yaitu menambahkan kelas baru ), jika tidak ditambahkan tanpa spasi.

Kode dapat ditulis ulang seperti yang Anda sarankan, tetapi Anda perlu menentukan yang h.classNameakan digunakan untuk perbandingan kebenaran, daripada menggunakan nilai sebenarnya, dalam operator terner, jadi pastikan Anda tidak repot-repot dengan penggabungan nilai bersamaan dengan melakukan operasi terner Anda:

h.className = h.className + (h.className ? ' error' : 'error');
David Hedlund
sumber
13
baik ya, undefinedtidak salah itu hanya diperlakukan seolah-olah
David Hedlund
4

Sisi kanan =operator dievaluasi dari kiri ke kanan. Begitu,

g.className = h.className + h.className ? ' error' : 'error';`

setara dengan

h.className = (h.className + h.className) ? ' error' : 'error';

Setara dengan

h.className += h.className ? ' error' : 'error';

Anda harus memisahkan pernyataan terner dalam tanda kurung

h.className = h.className + (h.className ? ' error' : 'error');
Justin Johnson
sumber
3
if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

harus setara dengan:

h.className += h.className ? ' error' : 'error';
Darin Dimitrov
sumber
1

Saya tahu ini adalah pertanyaan yang sangat lama, tetapi saya tidak 100% senang dengan jawaban mana pun karena semuanya tampak tidak lengkap. Jadi di sini kita pergi lagi dari kepala sekolah pertama:

Tujuan keseluruhan pengguna:

Meringkas kode: "Saya ingin menambahkan errornama kelas ke string, opsional dengan spasi di depan jika sudah ada nama kelas dalam string."

Solusi paling sederhana

Seperti yang ditunjukkan Kobi, 5 tahun yang lalu, memiliki ruang terdepan dalam nama kelas tidak akan menyebabkan masalah dengan browser yang dikenal, jadi solusi terpendek yang benar adalah:

h.className += ' error';

Itu seharusnya menjadi jawaban yang sebenarnya untuk masalah yang sebenarnya .


Bagaimanapun, pertanyaan yang diajukan adalah ...

1) Mengapa ini berhasil?

h.className += h.className ? ' error' : 'error'

Operator kondisional / ternary bekerja seperti pernyataan if, yang memberikan hasil jalur trueatau falseke variabel.

Jadi kode itu berfungsi karena dievaluasi hanya sebagai:

if (h.className IS NOT null AND IS NOT undefined AND IS NOT '') 
    h.className += ' error'
else
    h.className += 'error'

2) dan mengapa ini pecah?

h.className = h.className + h.className ? ' error' : 'error'

Pertanyaan tersebut menyatakan "yang memberikan [n] kesalahan di konsol saya", yang mungkin menyesatkan Anda sehingga mengira kode tersebut tidak berfungsi . Bahkan kode berikut tidak berjalan, tanpa kesalahan , tapi itu hanya kembali 'kesalahan' jika string tidak kosong dan 'kesalahan' jika string adalah kosong dan begitu tidak memenuhi persyaratan .

Kode itu selalu menghasilkan string yang hanya berisi ' error'atau 'error'karena dievaluasi ke kode pseudo ini:

if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
    h.className = ' error'
else
    h.className = 'error'

Alasan untuk ini adalah bahwa operator penjumlahan ( +untuk rakyat biasa) memiliki "prioritas" yang lebih tinggi (6) daripada operator bersyarat / terner (15). Saya tahu angkanya muncul di belakang

Diutamakan berarti bahwa setiap jenis operator dalam suatu bahasa dievaluasi dalam urutan tertentu yang telah ditentukan sebelumnya (dan tidak hanya kiri-ke-kanan).

Referensi: Prioritas Operator Javascript

Bagaimana mengubah urutan evaluasi:

Sekarang kami tahu mengapa gagal, Anda perlu tahu cara membuatnya bekerja.

Beberapa jawaban lain berbicara tentang mengubah prioritas , tetapi Anda tidak bisa . Prioritas sudah terprogram ke dalam bahasa. Itu hanya seperangkat aturan tetap ... Namun, Anda dapat mengubah urutan evaluasi ...

Alat di kotak alat kami yang dapat mengubah urutan evaluasi adalah operator pengelompokan (alias tanda kurung). Ini dilakukan dengan memastikan ekspresi dalam tanda kurung dievaluasi sebelum operasi di luar tanda kurung. Itu saja yang mereka lakukan, tapi itu sudah cukup.

Tanda kurung berfungsi hanya karena mereka (operator pengelompokan) memiliki prioritas lebih tinggi daripada semua operator lainnya ("sekarang ada level 0").

Dengan hanya menambahkan tanda kurung, Anda mengubah urutan evaluasi untuk memastikan pengujian bersyarat dilakukan terlebih dahulu, sebelum penggabungan string sederhana:

h.className = h.className + (h.className ? ' error' : 'error')

Sekarang saya akan meninggalkan jawaban ini untuk karat yang tidak terlihat di antara yang lain :)

Hilang Coding
sumber
1

Saya ingin memilih penjelasan tentang wayne:

<variable> = <expression> ? <true clause> : <false clause>

Mari pertimbangkan kedua kasus tersebut:

case 1:
h.className += h.className ? 'true' : 'false'     
  • operator penugasan bekerja dengan baik dan nilai ditambahkan
  • saat dijalankan untuk pertama kali, o / p: false
  • Kedua kalinya. o / p: falsetrue - nilai terus bertambah

case2: h.className = h.className + h.className? 'benar salah'

  • hasilnya tidak sama dengan kasus 1
  • saat dijalankan untuk pertama kali, o / p: false
  • Kedua kalinya. o / p: false - nilai tidak terus ditambahkan

explanation

Pada kode di atas, case 1 berfungsi dengan baik

sedangkan case2:

h.className = h.className + h.className ? 'true' : 'false'
is executed as 
 h.className = (h.className + h.className) ? 'true' : 'false'

h.className + h.className=> dianggap sebagai ekspresi untuk operator terner karena operator terner diberi prioritas lebih tinggi. jadi, selalu hasil dari ekspresi terner baru saja ditetapkan

Anda perlu menentukan prioritas dengan menggunakan tanda kurung

Anda perlu menentukan urutan evaluasi yang akan dipertimbangkan dengan bantuan tanda kurung agar kasus 2 berfungsi sebagai kasus 1

h.className = h.className + (h.className ? ' error' : 'error') 
Angelin Nadar
sumber
1
Terminologi di sini kurang tepat. Diutamakan yang melekat dalam bahasa, Anda tidak mendefinisikannya . Anda malah menentukan urutan evaluasi dengan memasukkan tanda kurung (yang memiliki prioritas lebih tinggi daripada semua operator lainnya).
Gone Coding
@TrueBlueAussie Saya menerimanya. saya menghargai niat Anda membaca +1
Angelin Nadar