Javascript Ternary operatörüyle operatör önceliği


116

Üçlü operatörle birlikte bu kodun ilk kısmına (+ =) başımı dolduramıyorum.

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

Bu kodun çalışma şeklini şu şekilde düşünüyorum:

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

Ancak bu doğru değil çünkü bu konsolumda bir hata veriyor.

Öyleyse sorum şu, bu kodu nasıl doğru bir şekilde yazmalıyım?

Yanıtlar:


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

Operatörün onun için çalışmasını istiyorsan, h.classNamebu konuda net olsan iyi olur.
Tabii ki, hiçbir zarar gelmemeli h.className += ' error', ama bu başka bir mesele.

Ayrıca, +bunun üçlü operatöre göre önceliğe sahip olduğunu unutmayın : JavaScript Operatör Önceliği


3
Bence herhangi bir zarar gelmemesi gerekirken h.className += ' error', eğer başlangıçta boşsa dizenin başında da bir boşluk bırakıyor. Üçlü işlemin amacının temiz görünümlü bir ip üretmek olduğuna inanıyorum.
JMTyler

@JMTyler - Ben de tam olarak bunu söylüyordum - Eğer her şey başlangıçtan itibaren bir yer tutmak için yapıldıysa, buna değmem. (uç durum tam jQuery veya XPath seçicilerini içerir). Her neyse, teşekkürler.
Kobi

Tek başına operatör öncelik uyarısı için @Kobi +1!
Ed Chapel

129

Bu şekilde düşün:

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

İfadenin çalıştırılma şekli temelde aşağıdaki gibidir:

  1. <expression>Doğru olarak değerlendiriliyor mu yoksa yanlış olarak mı değerlendiriliyor?
  2. Eğer <expression>değerlendirir true, sonra değeri <true clause>atanır <variable>, <false clause>göz ardı edilir ve bir sonraki ifadesi çalıştırıldı.
  3. Yanlış olarak <expression>değerlendirilirse <true clause>, yok sayılır ve değeri <false clause>atanır <variable>.

Bu ve diğer dillerde üçlü operatörle anlaşılması gereken önemli şey, hangi kodun içinde olursa olsun <expression>, değerlendirildiğinde bir mantıksal sonuç üretmesi gerektiğidir: doğru veya yanlış.

Örneğiniz durumunda, açıklamamdaki "atanmış" ifadesini "eklenen" ile veya varsa, kullandığınız steno aritmetik için benzer şekilde değiştirin.


Mükemmel yorumun uygun olup olmadığına dikkat edin :) Sol taraftaki ifadelerin neden önce "birlikte gruplandırıldığına" ilişkin açıklamaları atlar (örneğin +, koşullu / üçlü operatörden daha büyük önceliğe sahiptir (aslında koşullu operatör neredeyse her zaman sonuncudur) herhangi bir ifadede değerlendirilir).
Kodlama Gitti

10

+=Ne istediğini yapar, ama bunun sağında üçlü açıklamada, eğer çek h.classNameo tanımsız ise Falsey, o olurdu. Doğruysa (yani, bir sınıf adı zaten belirtilmişse), hata bir boşlukla eklenir (yani yeni bir sınıf ekleyerek ), aksi takdirde boşluk olmadan eklenir.

Kod önerdiğiniz gibi yeniden yazılabilir, ancak h.classNamebunun üçlü operatörde gerçek değerini kullanmak yerine doğruluk karşılaştırması için kullanılacağını belirtmeniz gerekir , bu nedenle değerlerin birleştirilmesiyle uğraşmadığınızdan emin olun Üçlü işleminizi yaparken aynı zamanda:

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

13
İyi evet, undefineddeğil yanlış olduğunu sanki sadece tedavi oluyor
David Hedlund

4

=Operatörün sağ tarafı soldan sağa doğru değerlendirilir. Yani,

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

eşdeğerdir

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

Eşdeğer olmak

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

Üçlü ifadeyi parantez içinde ayırmanız gerekir

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

3
if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

eşdeğer olmalıdır:

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

1

Bunun çok eski bir soru olduğunu biliyorum, ancak hepsi eksik göründüğü için cevapların hiçbirinden% 100 memnun değilim. İşte yine ilk müdürlerden başlıyoruz:

Kullanıcının genel amacı:

Kodu özetlemek: " Dizede zaten sınıf adları varsa isteğe bağlı olarak baştaki bir boşlukla birlikte bir dizeye bir errorsınıf adı eklemek istiyorum ."

En basit çözüm

Kobi'nin 5 yıl önce belirttiği gibi, sınıf adlarında lider bir alana sahip olmak, bilinen tarayıcılarda herhangi bir soruna neden olmayacağından, en kısa doğru çözüm aslında şu olacaktır:

h.className += ' error';

Yani olmalıydı gerçek cevabı için gerçek bir sorun .


Olursa olsun, sorulan sorular ...

1) Bu neden işe yaradı?

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

Koşullu / üçlü operatör, kendi trueveya falseyollarının sonucunu bir değişkene atayan bir if ifadesi gibi çalışır .

Böylece bu kod işe yaradı çünkü basitçe şu şekilde değerlendirildi:

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

2) ve bu neden kırıldı?

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

Soru, "konsolumda [n] hatası veren" olduğunu belirtir ve bu sizi yanlış bir şekilde kodun çalışmadığını düşünmeye sevk edebilir . Aslında şu kod olmadan çalışıyor mu hata , ama sadece döndürüyor 'hatası' dizesi eğer değildi boşaltmak ve 'hatası' dizesi eğer idi boş ve böylece gereksinimlerini karşılamak vermedi .

Bu kod her zaman yalnızca içeren bir dizeyle sonuçlanır ' error'veya 'error'bu sözde kodu değerlendirdiği için:

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

Bunun nedeni, toplama operatörünün ( +ortak halka) koşullu / üçlü operatörden (15) daha yüksek "önceliğe" (6) sahip olmasıdır. Numaraların geriye doğru göründüğünü biliyorum

Öncelik, basitçe, bir dildeki her bir operatör türünün belirli bir önceden tanımlanmış sırayla (sadece soldan sağa değil) değerlendirildiği anlamına gelir.

Referans: Javascript Operatör Önceliği

Değerlendirme sırası nasıl değiştirilir:

Şimdi neden başarısız olduğunu biliyoruz, nasıl çalıştıracağınızı bilmeniz gerekiyor.

Diğer bazı yanıtlar , önceliği değiştirmekten bahsediyor , ancak yapamazsınız . Öncelik, dile sabitlenmiştir. Bu sadece sabit bir kurallar dizisidir ... Bununla birlikte, değerlendirme sırasını değiştirebilirsiniz ...

Araç kutumuzdaki değerlendirme sırasını değiştirebilen araç , gruplama operatörüdür (parantez olarak da bilinir). Bunu, parantez içindeki ifadelerin parantez dışındaki işlemlerden önce değerlendirilmesini sağlayarak yapar . Tüm yaptıkları bu, ama bu kadar yeter.

Parantezler basitçe çalışırlar çünkü onlar (gruplama operatörleri) diğer tüm operatörlerden daha yüksek önceliğe sahiptir ("artık bir seviye 0 vardır").

Basitçe parantez ekleyerek , basit dize birleştirmeden önce koşullu testin gerçekleştirildiğinden emin olmak için değerlendirme sırasını değiştirirsiniz :

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

Şimdi bu cevabı diğerleri arasında görünmeden paslanmaya bırakacağım :)


1

Wayne'in açıklamasını seçmek istiyorum:

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

Her iki durumu da ele alalım:

case 1:
h.className += h.className ? 'true' : 'false'     
  • atama operatörü iyi çalışıyor ve değer eklenir
  • ilk çalıştırıldığında, o / p: false
  • 2. kez. o / p: falsetrue - değerler eklenmeye devam ediyor

case2: h.className = h.className + h.className? 'doğru yanlış'

  • sonuç durum 1 ile aynı değil
  • ilk çalıştırıldığında, o / p: false
  • 2. kez. o / p: false - değerler eklenmeye devam etmez

explanation

Yukarıdaki kodda, durum 1 iyi çalışıyor

oysa case2:

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

h.className + h.className=> Üçlü operatörün ifadesi olarak kabul edilir, çünkü üçlü operatör daha yüksek önceliklidir. bu nedenle, her zaman üçlü ifadenin sonucu sadece atanır

Parantez kullanarak önceliği tanımlamanız gerekir

Durum 2'nin durum 1 olarak çalışması için değerlendirmenin değerlendirilmesinin sırasını parantez yardımıyla belirlemeniz gerekir.

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

1
Buradaki terminoloji tam olarak doğru değil. Öncelik dilin doğasında vardır, onu siz tanımlamazsınız . Bunun yerine, parantezler ekleyerek (diğer tüm operatörlerden daha yüksek önceliğe sahip) değerlendirme sırasını tanımlıyorsunuz .
Kodlama Gitti

@TrueBlueAussie Kabul ediyorum. +1 okuduğunuz için minnettarım
Angelin Nadar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.