JSLint prevedeva "===" e invece vedeva "=="


90

Recentemente stavo eseguendo parte del mio codice tramite JSLint quando ho riscontrato questo errore. La cosa che penso sia divertente di questo errore è che assume automaticamente che tutti i == dovrebbero essere ===.

Ha davvero senso? Ho notato molti casi in cui non vorresti confrontare il tipo e sono preoccupato che questo possa effettivamente causare problemi.

La parola "Previsto" implicherebbe che questo dovrebbe essere fatto OGNI volta ..... Questo è ciò che non ha senso per me.


7
Mi sono imbattuto anche in questo con JSLint. Ho effettuato un aggiornamento da == a === e in realtà ha rotto il codice precedentemente funzionante.
kemiller2002

5
Se il tuo codice ha più di 100 righe, non passerà jslint, davvero, è impossibile.

3
"Broke" è una parola troppo forte. Ha cambiato il significato del tuo codice. Se stavi facendo un myVar == nullcontrollo, sì, grandi cambiamenti. ; ^) L'argomento di Crockford è che ha reso il significato del codice più preciso, e questo è difficile da argomentare.
ruffin

Risposte:


127

IMO, usare ciecamente ===, senza cercare di capire come funziona la conversione del tipo non ha molto senso.

Il timore principale dell'operatore Uguale a ==è che le regole di confronto a seconda dei tipi confrontati possano rendere l'operatore non transitivo, ad esempio, se:

A == B AND
B == C

Non garantisce realmente che:

A == C

Per esempio:

'0' == 0;   // true
 0  == '';  // true
'0' == '';  // false

L'operatore Strict Equals ===non è realmente necessario quando si confrontano valori dello stesso tipo, l'esempio più comune:

if (typeof foo == "function") {
  //..
}

Confrontiamo il risultato typeofdell'operatore, che è sempre una stringa , con una stringa letterale ...

O quando conosci le regole di coercizione del tipo, ad esempio, controlla se qualcosa è nullo undefinedqualcosa del genere:

if (foo == null) {
  // foo is null or undefined
}

// Vs. the following non-sense version:

if (foo === null || typeof foo === "undefined") {
  // foo is null or undefined
}

1
Odio questa regola di JSLint. Penso che il vero problema sia che le persone non dovrebbero usare gli operatori in modi che non capiscono (ironicamente si tratta spesso dello stesso tipo di persone che sostituirebbero ciecamente "===" con "=="). Certo, ci sono alcuni casi comuni che si verificano quando si confronta il numero 0 con varie stringhe, ma se si confrontano dati non correlati come 0 == 'questa è una stringa' - Il codice probabilmente ha problemi più grandi del doppio uguale! Se sai con certezza con quali tipi hai a che fare e sai esattamente come interagiscono con ==, allora penso che dovresti usarlo.
Jon

3
@ Jon Il punto di forza ===dell'operatore è la chiarezza del codice. Non esiste una situazione ragionevole da utilizzare in ==quanto non sarà mai chiara e comprensibile come l'operatore di identità. Non si tratta di capire o meno gli operatori, si tratta di utilizzare quello che rende il codice più facilmente leggibile quasi senza spese. Gli unici sviluppatori che stanno discutendo contro l'operatore di identità sono sviluppatori solisti e persone che non lavorano in team. Per definizione, le persone il cui codice non viene esaminato da abbastanza occhi.
Alternatex

2
Trovo che il confronto == null sia quasi essenziale. Il problema diventa ancora meno importante se il tuo codice è ben testato.
Jon

1
Ci sono infatti momenti in cui l'uso di == è essenziale per eseguire il test richiesto. se foo.toString () funzionerà in modo prevedibile e una stringa semplice deve essere testata rispetto a quell'output, allora scrivere foo == stringToTest è molto più pulito di foo.toString () === stringToTest.
Crispen Smith

2
@Alternatex Se il punto era la chiarezza non avrebbero dovuto renderla TRIPLA uguale! Nessun principiante lo capisce. Almeno il doppio uguale è noto da altre lingue. Inoltre, there is no reasonable situationè un grave errore. Pensa ai tipi Javascript (nativi) Numbere String. La loro esistenza prova che gli autori Javascript avevano in mente alcuni casi d'uso ==. Pensi davvero che la new String('hi') === 'hi'valutazione falsesia molto chiara? Per favore scrivi uno snippet di codice che metta alla prova l'argomento della tua funzione contro l' 'hi'accettazione sia di String che di string e dimmi che è chiaro.
Stijn de Witt

25

JSLint è intrinsecamente più difensivo di quanto consentito dalla sintassi Javascript.

Dalla documentazione di JSLint:

Gli operatori ==e !=digitano la coercizione prima del confronto. Questo è un male perché fa sì ' \t\r\n' == 0che sia vero. Questo può mascherare errori di tipo.

Quando si confronta uno dei seguenti valori, utilizzare gli operatori ===o !==(che non digitano coercizione):0 '' undefined null false true

Se ti interessa solo che un valore sia vero o falso , usa la forma abbreviata. Invece di

(foo != 0)

basta dire

(foo)

e invece di

(foo == 0)

dire

(!foo)

Gli operatori ===e !==sono preferiti.


8
Devo concludere che le persone di JSLint lavorano in una torre d'avorio molto alta da cui non escono mai. Javascript è stato progettato per essere utilizzato con l' ==operatore. Il ===è un caso particolare ... JSLint cerca di far sembrare che usando ==avrebbe in qualche modo sbagliato ... Comunque, provate questo: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. I tipi primitivi hanno classi corrispondenti che li sostituiscono ( Number, String) e Javascript dipende ==dall'operatore per rendere naturale il confronto.
Stijn de Witt,

17

Tieni presente che JSLint rafforza l'idea di una persona su cosa dovrebbe essere un buon JavaScript. È comunque necessario usare il buon senso quando si implementano le modifiche suggerite.

In generale, il confronto tra tipo e valore renderà il tuo codice più sicuro (non ti imbatterai in un comportamento imprevisto quando la conversione del tipo non fa quello che pensi che dovrebbe).


4
Inoltre non può essere intelligente dal punto di vista del contesto come un programmatore. Funziona solo sulla base del fatto che la maggior parte degli utenti viene inciampata dalla conversione automatica del tipo inerente al sistema (come la violenza - "aiutami, aiutami a essere represso!")
Rudu

14

Triplo uguale è diverso da doppio uguale perché oltre a controllare se i due lati hanno lo stesso valore, triplo uguale controlla anche che siano dello stesso tipo di dati.

Quindi ("4" == 4)è vero, mentre ("4" === 4)è falso.

Triple-equal funziona anche leggermente più velocemente, perché JavaScript non deve perdere tempo a fare conversioni di tipo prima di darti la risposta.

JSLint è deliberatamente mirato a rendere il tuo codice JavaScript il più rigoroso possibile, con l'obiettivo di ridurre i bug oscuri. Evidenzia questo genere di cose per cercare di farti programmare in un modo che ti costringa a rispettare i tipi di dati.

Ma la cosa buona di JSLint è che è solo una guida. Come si dice sul sito, ferirà i tuoi sentimenti, anche se sei un ottimo programmatore JavaScript. Ma non dovresti sentirti obbligato a seguire i suoi consigli. Se hai letto quello che ha da dire e lo capisci, ma sei sicuro che il tuo codice non si romperà, allora non sei costretto a cambiare nulla.

Puoi anche dire a JSLint di ignorare le categorie di controlli se non vuoi essere bombardato da avvisi per i quali non farai nulla.


3
Non ho chiesto "Cos'è ===", quindi non sono sicuro del motivo per cui hai risposto.
Metropolis

8
@Metropolis: se non altro, come sfondo nel caso in cui qualcun altro leggesse la risposta che non lo sapeva. Tuttavia, ho provato a rispondere alla tua domanda nei paragrafi successivi.
Spudley

@Spudley + 1 per le informazioni aggiuntive e utili
Ben Junior

1
sì, è 10-100 volte più veloce: jsperf speed test
vladkras

8

Una citazione da http://javascript.crockford.com/code.html :

=== e! == Operatori.

È quasi sempre meglio usare gli operatori === e! ==. Gli operatori == e! = Digitano coercizione. In particolare, non utilizzare == per confrontare con valori falsi.

JSLint è molto rigoroso, il loro "webjslint.js" non supera nemmeno la propria convalida.


Bel chiarimento. È vero, sulla webjslint.jsnon convalida, sebbene la maggior parte degli errori che vedo in questo momento hanno a che fare con la spaziatura. Chiaramente, è necessario usare il buon senso e il giudizio ragionevole quando si esamina JavaScript utilizzando JSLint.
hotshot309

L'uso della parola alwayssqualifica automaticamente questa citazione come saggezza. I programmatori intelligenti non sono dogmatici. Usano ciò che è meglio nella situazione data. E accolgono e abbracciano qualsiasi strumento integrato nel cuore del linguaggio, non semplicemente lo liquidano con a just never touch it. In conclusione: il mio codice è più breve (e non solo per il salvataggio di un =carattere), quindi il mio sito si carica più velocemente, a un costo di larghezza di banda inferiore, quindi il mio utente è servito meglio.
Stijn de Witt,

4

Se vuoi verificare la falsità. JSLint non consente

if (foo == null)

ma permette

if (!foo)

Usa ===, consigliato da JSLint.
clickbait

1
@NarawaGames Questa soluzione è perfettamente accettabile.

Questa risposta non è buona. Il fatto è che entrambi significano qualcos'altro. foo == nullverifica la presenza di null o undefined. !fooverifica la presenza di stringhe nulle, non definite, 0 e vuote.
Markos

@Markos Questa risposta vuole essere un'alternativa utile per rendere felice JSLint e mantenere intatta la logica del codice, non per essere un equivalente esatto. Questo è il motivo per cui ho anteposto alla risposta "Se si verifica la falsità"
nano2nd

3

Per aiutare a spiegare questa domanda e anche a spiegare perché NetBeans (da) 7.3 ha iniziato a mostrare questo avviso, questo è un estratto della risposta sul bug tracker di NetBeans quando qualcuno lo ha segnalato come un bug:

È buona norma utilizzare === anziché == in JavaScript.

Gli operatori == e! = Digitano la coercizione prima del confronto. Questo è negativo perché fa sì che '\ t \ r \ n' == 0 sia vero. Questo può mascherare errori di tipo. JSLint non può determinare in modo affidabile se == viene usato correttamente, quindi è meglio non usare affatto == e! = E usare sempre gli operatori === e! == più affidabili invece.

Riferimento


1
Ho trovato questo errore solo ora anche usando Netbeans. È strano che lo trattassero con severità di avvertimento a causa del bizzarro esempio di caso fornito.
omikes

1
voglio dire, è vero, ma ci sono molti casi d'uso in cui la persona sa che le due cose confrontate saranno dello stesso tipo, quindi sembra strano che a causa di questo strano caso in cui un ritorno a capo potrebbe essere paragonato al numero zero è il motivo per cui tutti gli usi di == sono considerati errati. sto scoprendo però che === è più veloce, poiché non vengono eseguite conversioni di tipo. sono sorpreso di non averlo scoperto prima di netbeans.
omikes

@oMiKeY Sì, capisco cosa intendi, avrebbero potuto fornire esempi più realistici!
EM-Creations

2

Beh, non può davvero causare problemi, ti sta solo dando consigli. Prendere o lasciare. Detto questo, non sono sicuro di quanto sia intelligente. Potrebbero esserci contesti in cui non lo presenta come un problema.


1
ma perché viene usata la parola "previsto"? Ciò fa sembrare che dovresti sempre farlo.
Metropolis

4
Il valutatore sta cercando una risposta valida, poiché sta cercando di convalidarla. Se non ottiene una risposta valida, non è quello che si aspettava. Il validatore parte dal presupposto che tutto sia a posto e poi indica gli errori mentre attraversa il codice. Non capisce necessariamente cosa sia una risposta non valida, sa solo quando ne vede una non valida. Potrebbe anche funzionare al contrario, cercando deliberatamente codice errato secondo le regole di ciò che è cattivo. Whitelisting vs blacklist.
Rushyo

La domanda era "Ha davvero senso?". Data questa domanda, sì, lo fa. Inoltre, è stato cinque anni fa . Gesù.
Rushyo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.