JSLint attendu '===' et a plutôt vu '=='

90

Récemment, j'exécutais une partie de mon code via JSLint lorsque j'ai rencontré cette erreur. La chose que je trouve amusante à propos de cette erreur, c'est qu'elle suppose automatiquement que tout == doit être ===.

Cela a-t-il vraiment un sens? Je pourrais voir un grand nombre de cas où vous ne voudriez pas comparer le type, et je crains que cela puisse causer des problèmes.

Le mot «prévu» impliquerait que cela devrait être fait CHAQUE fois ..... C'est ce qui n'a pas de sens pour moi.

Métropole
la source
7
J'ai rencontré cela aussi avec JSLint. J'ai fait une mise à jour de == vers === et cela a en fait cassé le code précédemment fonctionnel.
kemiller2002
5
Si votre code a plus de 100 lignes, il ne passera pas jslint, vraiment, c'est impossible.
3
«Cassé» est un mot trop fort. Cela a changé la signification de votre code. Si vous faisiez une myVar == nullvérification, oui, de grands changements. ; ^) L'argument de Crockford est qu'il a rendu le sens du code plus précis, et c'est difficile à argumenter.
ruffin

Réponses:

127

IMO, utiliser aveuglément ===, sans essayer de comprendre comment fonctionne la conversion de type n'a pas beaucoup de sens.

La principale crainte à propos de l'opérateur Equals ==est que les règles de comparaison en fonction des types comparés peuvent rendre l'opérateur non transitif, par exemple, si:

A == B AND
B == C

Ne garantit pas vraiment que:

A == C

Par exemple:

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

L'opérateur Strict Equals ===n'est pas vraiment nécessaire lorsque vous comparez des valeurs du même type, l'exemple le plus courant:

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

Nous comparons le résultat de l' typeofopérateur, qui est toujours une chaîne , avec une chaîne littérale ...

Ou lorsque vous connaissez les règles de coercition de type, par exemple, vérifiez si quelque chose est nullou undefinedquelque chose:

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
}
Christian C. Salvadó
la source
1
Je déteste cette règle de JSLint. Je pense que le vrai problème est que les gens ne devraient pas utiliser les opérateurs d'une manière qu'ils ne comprennent pas (ironiquement, ce sont souvent le même genre de personnes qui remplaceraient aveuglément «===» par «==»). Bien sûr, il y a quelques cas habituels qui surviennent lors de la comparaison du nombre 0 avec différentes chaînes, mais si vous comparez des données non liées comme 0 == 'c'est une chaîne' - Votre code a probablement plus de problèmes que le double égal! Si vous savez avec certitude à quels types vous avez affaire et comment ils interagissent exactement avec ==, alors je pense que vous devriez l'utiliser.
Jon
3
@Jon Le but de l' ===opérateur est la clarté du code. Il n'y a pas de situation raisonnable à utiliser ==car elle ne sera jamais aussi claire et compréhensible que l'opérateur d'identité. Il ne s'agit pas de savoir si vous comprenez les opérateurs ou non, il s'agit d'utiliser celui qui rend votre code plus facilement lisible presque sans frais. Les seuls développeurs qui s'opposent à l'opérateur d'identité sont les développeurs solo et les personnes qui ne travaillent pas en équipe. Par définition, les gens dont le code n'est pas examiné par suffisamment d'yeux.
Alternatex
2
Je trouve que la comparaison == null est presque essentielle. Le problème devient encore moins important si votre code est bien testé.
Jon
1
Il y a en effet des moments où l'utilisation de == est indispensable pour effectuer le test requis. si foo.toString () fonctionnera de manière prévisible et qu'une chaîne simple doit être testée par rapport à cette sortie, alors l'écriture de foo == stringToTest est beaucoup plus propre que foo.toString () === stringToTest.
Crispen Smith
2
@Alternatex Si le point était la clarté, ils n'auraient pas dû en faire un TRIPLE égal! Aucun débutant ne le comprend. Au moins le double égal est connu d'autres langues. Il y a également there is no reasonable situationune inexactitude flagrante. Pensez aux types Javascript (natifs) Numberet String. Leur existence prouve que les auteurs de Javascript avaient en tête certains cas d'utilisation ==. Pensez-vous vraiment new String('hi') === 'hi'qu'évaluer falseest très clair? Veuillez écrire un extrait de code qui teste votre argument de fonction contre l' 'hi'acceptation à la fois de String et de string et dites-moi que c'est clair.
Stijn de Witt
25

JSLint est intrinsèquement plus défensif que ne le permet la syntaxe Javascript.

À partir de la documentation JSLint:

Les opérateurs ==et !=saisissent la coercition avant de comparer. C'est mauvais parce que c'est ' \t\r\n' == 0vrai. Cela peut masquer les erreurs de type.

Lorsque vous comparez à l'une des valeurs suivantes, utilisez les opérateurs ===ou !==(qui ne font pas de coercition de type):0 '' undefined null false true

Si vous vous souciez seulement qu'une valeur soit vraie ou fausse , utilisez la forme courte. Au lieu de

(foo != 0)

dis le

(foo)

et au lieu de

(foo == 0)

dire

(!foo)

Les opérateurs ===et !==sont préférés.

Daniel Vandersluis
la source
8
Je dois conclure que les gens de JSLint travaillent dans une très haute tour d'ivoire dont ils ne sortent jamais. Javascript a été conçu pour être utilisé avec l' ==opérateur. Le ===est un cas particulier ... JSLint essaie de faire croire que l' utilisation ==serait en quelque sorte tort ... Cependant, essayez ceci: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. Les types primitifs ont des classes correspondantes qui les remplacent ( Number, String) et Javascript dépend de l' ==opérateur pour rendre la comparaison naturelle.
Stijn de Witt
17

Gardez à l'esprit que JSLint applique une idée de ce que devrait être un bon JavaScript. Vous devez toujours faire preuve de bon sens lors de la mise en œuvre des changements qu'il suggère.

En général, comparer le type et la valeur rendra votre code plus sûr (vous ne rencontrerez pas de comportement inattendu lorsque la conversion de type ne fait pas ce que vous pensez qu'elle devrait).

Justin Niessner
la source
4
De plus, il ne peut pas être aussi intelligent en contexte qu'un programmeur. Cela fonctionne simplement sur la base que la plupart des utilisateurs sont déclenchés par la conversion automatique de type inhérente au système (comme la violence - "aidez-moi, je suis réprimé!")
Rudu
14

Triple-égal est différent de double-égal car en plus de vérifier si les deux côtés ont la même valeur, triple-égal vérifie également qu'ils sont du même type de données.

C'est ("4" == 4)vrai, alors que ("4" === 4)c'est faux.

Triple-égal s'exécute également un peu plus rapidement, car JavaScript n'a pas à perdre de temps à effectuer des conversions de type avant de vous donner la réponse.

JSLint vise délibérément à rendre votre code JavaScript aussi strict que possible, dans le but de réduire les bogues obscurs. Il met en évidence ce genre de chose pour essayer de vous amener à coder d'une manière qui vous oblige à respecter les types de données.

Mais la bonne chose à propos de JSLint est que ce n'est qu'un guide. Comme on dit sur le site, cela vous blessera, même si vous êtes un très bon programmeur JavaScript. Mais vous ne devriez pas vous sentir obligé de suivre ses conseils. Si vous avez lu ce qu'il a à dire et que vous le comprenez, mais que vous êtes sûr que votre code ne se cassera pas, alors vous n'êtes pas obligé de changer quoi que ce soit.

Vous pouvez même dire à JSLint d'ignorer les catégories de vérifications si vous ne voulez pas être bombardé d'avertissements contre lesquels vous n'allez rien faire.

Spudley
la source
3
Je n'ai pas demandé "Qu'est-ce que ===", donc je ne sais pas pourquoi vous y avez répondu.
Metropolis
8
@Metropolis: si pour aucune autre raison, alors comme arrière-plan au cas où quelqu'un d'autre lirait la réponse qui ne savait pas. J'ai cependant essayé de répondre à votre question dans les paragraphes suivants.
Spudley le
@Spudley + 1 pour les informations complémentaires et utiles
Ben Junior
1
oui, c'est 10-100 fois plus rapide: test de vitesse
jsperf
8

Une citation de http://javascript.crockford.com/code.html :

=== et! == Opérateurs.

Il est presque toujours préférable d'utiliser les opérateurs === et! ==. Les opérateurs == et! = Saisissent la coercition. En particulier, n'utilisez pas == pour comparer avec des valeurs fausses.

JSLint est très strict, leur 'webjslint.js' ne passe même pas leur propre validation.

Lekensteyn
la source
Belle clarification. C'est vrai, à propos de la webjslint.jsnon-validation - bien que la plupart des erreurs que je vois actuellement soient liées à l'espacement. De toute évidence, il faut faire preuve de bon sens et de jugement raisonnable lors de l'examen de JavaScript en utilisant JSLint.
hotshot309
L'utilisation du mot alwaysdisqualifie automatiquement cette citation en tant que sagesse. Les programmeurs intelligents ne sont pas dogmatiques. Ils utilisent ce qu'il y a de mieux dans la situation donnée. Et ils accueillent et adoptent tout outil intégré au cœur même du langage, pas seulement le rejeter avec un just never touch it. Bottom line: Mon code est plus court (et pas seulement en sauvegardant un =caractère), donc mon site se charge plus rapidement, à moindre coût en bande passante, donc mon utilisateur est mieux servi.
Stijn de Witt
4

Si vous voulez tester la fausseté. JSLint ne permet pas

if (foo == null)

mais permet

if (!foo)
nano2nd
la source
Utilisez ===, ce que JSLint recommande.
clickbait
1
@NarawaGames Cette solution est parfaitement acceptable.
Cette réponse n'est pas bonne. Le fait est que ces deux éléments signifient autre chose. foo == nullrecherche null ou indéfini. !foovérifie les chaînes nulles, indéfinies, 0 et vides.
Markos
@Markos Cette réponse est censée être une alternative utile pour rendre JSLint heureux et garder votre logique de code intacte, pas pour être un équivalent exact. C'est pourquoi j'ai préfixé la réponse par "Si vous vérifiez la fausseté"
nano2nd
3

Pour aider à expliquer cette question et également expliquer pourquoi NetBeans (à partir de) 7.3 a commencé à afficher cet avertissement, ceci est un extrait de la réponse sur le suivi des bogues NetBeans lorsque quelqu'un a signalé cela comme un bogue:

Il est recommandé d'utiliser === plutôt que == en JavaScript.

Les opérateurs == et! = Saisissent la coercition avant de comparer. Ceci est mauvais car cela rend vrai '\ t \ r \ n' == 0. Cela peut masquer les erreurs de type. JSLint ne peut pas déterminer de manière fiable si == est utilisé correctement, il est donc préférable de ne pas utiliser du tout == et! = Et de toujours utiliser à la place les opérateurs === et! == les plus fiables.

Référence

Créations EM
la source
1
J'ai également trouvé cette erreur en utilisant Netbeans. Il est étrange qu'ils traitent cela avec une sévérité d'avertissement en raison de l'exemple de cas bizarre qu'ils ont fourni.
omikes
1
je veux dire, c'est vrai, mais il existe de nombreux cas d'utilisation dans lesquels la personne sait que les deux choses comparées seront du même type, il semble donc étrange qu'en raison de cet étrange cas où un retour chariot puisse être comparé au nombre zéro est la raison pour laquelle toutes les utilisations de == sont considérées comme incorrectes. Je découvre cependant que === est plus rapide, car aucune conversion de type n'est effectuée. Je suis surpris de ne pas avoir découvert cela avant netbeans.
omikes
@oMiKeY Oui je vois ce que tu veux dire, ils auraient pu donner des exemples plus réalistes!
EM-Creations
2

Eh bien, cela ne peut pas vraiment causer de problèmes, c'est juste vous donner des conseils. À prendre ou a laisser. Cela dit, je ne sais pas à quel point c'est intelligent. Il peut bien y avoir des contextes dans lesquels cela ne le présente pas comme un problème.

Rushyo
la source
mais pourquoi le mot «attendu» est-il utilisé? Cela donne l'impression que vous devriez toujours faire cela.
Metropolis
4
L'évaluateur recherche une réponse valide, car il essaie de la valider. S'il n'obtient pas de réponse valide, ce n'est pas ce à quoi il s'attendait. Le validateur part de l'hypothèse que tout va bien, puis signale les erreurs lorsqu'il parcourt le code. Il ne comprend pas nécessairement ce qu'est une réponse invalide, il sait juste quand il en voit une non valide. Cela pourrait également fonctionner à l'inverse, en recherchant délibérément le mauvais code selon les règles de ce qui est mauvais. Liste blanche ou liste noire.
Rushyo
La question était "Cela a-t-il vraiment un sens?". Compte tenu de cette question, oui, c'est le cas. De plus, c'était il y a cinq ans . Jésus.
Rushyo