Perché il confronto tra stringhe e numbers funziona in Javascript

Sto cercando di confrontare un valore proveniente da un field di text HTML con interi. E funziona come previsto. La condizione è –

x >= 1 && x <= 999; 

Dove x è il valore del field di text. Condizione restituisce true each volta che il valore è compreso tra 1-999 (incluso), altrimenti false . Il problema è che il valore proveniente dal field di text è di tipo string e lo sto confrontando con i tipi interi. È opportuno avere questo confronto come questo o dovrei usare parseInt () per convertire x in integer?

Poiché JavaScript definisce >= e <= (e molti altri operatori) in un modo che consente loro di impegnare i loro operandi su diversi tipi. È solo una parte della definizione dell'operatore.

Nel caso di < , > , <= , e >= , i dettagli sono descritti in § 11.8.5 della specifica . La versione corta è: Se entrambi gli operandi sono stringhe (dopo essere stati costretti da oggetti, se necessario), fa un confronto di stringhe. Altrimenti, impegna gli operandi ai numbers e fa un confronto numbersco.

Di conseguenza, ottenete risultati divertenti, come quello "90" > "100" (entrambi sono stringhe, è un confronto di stringhe) ma "90" < 100 (uno dei quali è un numero, è un confronto numbersco). 🙂

È opportuno avere questo confronto come questo o dovrei usare parseInt () per convertire x in integer?

È una questione di opinione. Alcune persone pensano che è giusto contare sulla coercizione implicita; altri pensano che non lo sia. Ci sono alcuni argomenti oggettivi. Ad esempio, supponiate di aver fatto affidamento su una conversione implicita ed è stato bello perché hai avuto quelle costanti numbersche, ma in seguito hai confrontato x con un altro valore ottenuto da un field di input. Ora stai confrontando le stringhe, ma il codice sembra uguale. Ma ancora una volta, è una questione di opinione e devi fare la tua scelta.

Se decidi di convertire esplicitamente i numbers prima, il parseInt può o non essere quello che vuoi e non fa la stessa cosa della conversione implicita. Ecco un rundown di opzioni:

  • parseInt(str[, radix]) – Converte tanto l'inizio della string quanto può in un numero integer (numero integer), ignorando i caratteri extra alla fine . Quindi il parseInt("10x") è 10 ; la x viene ignorata. Support un argomento opzionale radix (numero base), quindi parseInt("15", 16) è 21 ( 15 in esadecimale). Se non esiste un raggio, assumiamo il decimale, a less che la string inizia con 0x (o 0X ), nel qual caso ignora e assume hex. (Alcuni browser utilizzati per trattare le stringhe che iniziano da 0 come ottale, che il comportmento non è mai stato specificato e fu [specificamente negato] [2] nella specifica ES5.) Restituisce NaN se non si trovano cifre parseable.

  • parseFloat(str) – Come parseInt , ma con numbers a virgola mobile e support solo decimale. Ancora i caratteri extra della string vengono ignorati, quindi parseFloat("10.5x") è 10.5 (la x viene ignorata). Poiché solo il decimale è supportto, parseFloat("0x15") è 0 (perché l'analisi termina alla x ). Restituisce NaN se non si trovano cifre parseable.

  • Unary + , ad esempio +str(ad esempio, conversione implicita) Converte l' intera string su un numero utilizzando la virgola mobile e la notazione del numero standard di JavaScript (solo cifre e un punto decimale = decimale, prefisso 0x = hex, 0o prefisso octale [ES2015 + , alcune implementazioni lo estendono per trattare un leader 0 come ottale, ma non in modalità rigorosa). +"10x" è NaN perché la x non viene ignorata. +"10" è 10 , +"10.5" è 10.5 , +"0x15" è 21 , +"0o10" è 8 [ES2015 +]. Ha un getcha: +"" è 0 , non NaN come ci si potrebbe aspettare.

  • Number(str) – Esattamente come la conversione implicita (ad esempio, come l'unaria + sopra), ma più lenta su alcune implementazioni. (Non che probabilmente avrà importnza.)

Quindi, se è bene che i bit extra sulla string vengono ignorati, il parseInt o il parseFloat sono benissimo. parseInt è abbastanza utile per specificare il radix. Unary + è utile per assicurare che tutta la string sia considerata. Scegli la tua scelta. 🙂

E infine: se stai convertendo in numero e vuoi sapere se il risultato è NaN , potrebbe essere tentato di fare if (convertedValue === NaN) . Ma questo non funziona , perché come sottolinea Rick, i confronti che coinvolgono NaN sono sempre falsi. Invece, è if (isNaN(convertedValue)) .

I documenti di MDN su Comparison indicano che gli operandi vengono convertiti in un tipo comune prima di confrontare (con l'operatore che stai utilizzando):

Il confronto più astratto (ad esempio ==) converte gli operandi nello stesso tipo prima di effettuare il confronto. Per i confronti estratti relazionali (ad esempio, <=), gli operandi vengono prima convertiti in primitive, quindi nello stesso tipo, prima del confronto.

Avrebbe solo bisogno di applicare parseInt() se si utilizza una rigorosa comparazione, che non esegue il casting automatico prima di confrontarlo.

È necessario utilizzare parseInt se var è una string. Aggiungi = per confrontare il valore del datatype :

 parseInt(x) >== 1 && parseInt(x) <== 999;