JSLint ожидал '===' и вместо этого увидел '=='

90

Недавно я запускал часть своего кода через JSLint, когда обнаружил эту ошибку. Мне кажется забавным в этой ошибке то, что она автоматически предполагает, что все == должно быть ===.

Это действительно имеет смысл? Я видел много примеров, в которых вы не хотели бы сравнивать типы, и меня беспокоит, что это действительно может вызвать проблемы.

Слово «Ожидается» подразумевает, что это нужно делать ВСЕГДА ... Это то, что для меня не имеет смысла.

Мегаполис
источник
7
Я тоже столкнулся с этим с JSLint. Я сделал обновление с == до ===, и оно фактически сломало ранее работавший код.
kemiller2002,
5
Если в вашем коде более 100 строк, он не пройдет jslint, это действительно невозможно.
3
«Сломался» - слишком сильное слово. Это изменило значение вашего кода. Если бы вы делали myVar == nullпроверку, да, большие изменения. ; ^) Крокфорд утверждает, что это сделало смысл кода более точным, и с этим трудно спорить.
ruffin

Ответы:

127

ИМО, слепое использование ===, не пытаясь понять, как работает преобразование типов , не имеет большого смысла.

Основное опасение по поводу оператора Equals ==состоит в том, что правила сравнения в зависимости от сравниваемых типов могут сделать оператор нетранзитивным, например, если:

A == B AND
B == C

На самом деле не гарантирует, что:

A == C

Например:

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

Оператор Strict Equals на ===самом деле не нужен, когда вы сравниваете значения одного и того же типа, самый распространенный пример:

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

Мы сравниваем результат typeofоператора, который всегда является строкой , со строковым литералом ...

Или, например, когда вы знаете правила приведения типов, проверьте, есть ли что-то nullили undefinedчто-то:

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
Я ненавижу это правило JSLint. Я думаю, что настоящая проблема в том, что люди не должны использовать операторы способами, которых они не понимают (по иронии судьбы, это часто те же люди, которые слепо заменяют '===' на '=='). Конечно, есть несколько обычных случаев, которые возникают при сравнении числа 0 с различными строками, но если вы сравниваете несвязанные данные, такие как 0 == 'this is a string' - ваш код, вероятно, имеет большие проблемы, чем двойное равенство! Если вы точно знаете, с какими типами имеете дело, и знаете, как именно они взаимодействуют с ==, то я думаю, вам стоит его использовать.
Джон
3
@Jon Суть ===оператора - ясность кода. Нет разумной ситуации для использования, ==поскольку она никогда не будет такой ясной и понятной, как оператор идентификации. Дело не в том, понимаете ли вы операторы или нет, а в том, чтобы использовать тот, который делает ваш код более читабельным почти без затрат. Единственные разработчики, которые выступают против оператора идентификации, - это индивидуальные разработчики и люди, которые не работают в команде. По определению, люди, код которых не просматривается достаточным количеством глаз.
Alternatex
2
Я считаю, что сравнение == null почти необходимо. Проблема становится еще менее важной, если ваш код хорошо протестирован.
Джон
1
На самом деле бывают случаи, когда использование == необходимо для выполнения необходимого теста. если foo.toString () будет работать предсказуемым образом, и простая строка должна быть протестирована на этом выходе, тогда запись foo == stringToTest намного чище, чем foo.toString () === stringToTest.
Криспен Смит
2
@Alternatex Если бы дело было в ясности, они не должны были делать это ТРОЙНО равным! Ни один новичок этого не понимает. По крайней мере, двойное равенство известно из других языков. Кроме того, there is no reasonable situationэто грубое искажение. Подумайте о (родных) типах Javascript Numberи String. Их существование доказывает, что авторы Javascript имели в виду определенные варианты использования ==. Вы действительно думаете, что new String('hi') === 'hi'оценивать falseочень ясно? Напишите фрагмент кода, который проверяет аргумент вашей функции на предмет 'hi'принятия и String, и String, и скажите мне, что это ясно.
Stijn de Witt
25

JSLint по своей природе более оборонительный, чем позволяет синтаксис Javascript.

Из документации JSLint:

==И !=операторы делают тип принуждения перед сравнением. Это плохо, потому что это ' \t\r\n' == 0правда. Это может замаскировать типовые ошибки.

При сравнении с любым из следующих значений используйте операторы ===или !==(которые не выполняют приведение типов):0 '' undefined null false true

Если вас беспокоит только то, что значение является правдивым или ложным , используйте краткую форму. Вместо того

(foo != 0)

просто скажи

(foo)

и вместо

(foo == 0)

сказать

(!foo)

Операторы ===и !==являются предпочтительными.

Даниэль Вандерслуис
источник
8
Я должен заключить, что люди из JSLint работают в какой-то очень высокой башне из слоновой кости, из которой они никогда не выберутся. Javascript был разработан для использования с ==оператором. ===Это особый случай ... JSLint пытается сделать это , похоже , как с помощью ==так или иначе неправильно ... Впрочем, попробуйте это: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. У примитивных типов есть соответствующие классы, которые их заменяют ( Number, String), а Javascript зависит от ==оператора, чтобы сделать сравнение естественным.
Stijn de Witt
17

Имейте в виду, что JSLint навязывает одному человеку представление о том, каким должен быть хороший JavaScript. Вам по-прежнему нужно руководствоваться здравым смыслом при реализации предлагаемых им изменений.

В общем, сравнение типа и значения сделает ваш код более безопасным (вы не столкнетесь с неожиданным поведением, когда преобразование типа не сделает то, что, по вашему мнению, должно).

Джастин Нисснер
источник
4
К тому же он не может быть таким контекстно-умным, как программист. Это просто работает на том основании, что большинство пользователей сбиваются с пути из-за автоматического преобразования типов, присущего системе (например, насилие - «помогите, помогите, меня подавляют!»)
Руду
14

Тройное равенство отличается от двойного равенства, потому что помимо проверки того, являются ли две стороны одинаковыми значениями, тройное равенство также проверяет, что они имеют один и тот же тип данных.

Так ("4" == 4)верно, тогда ("4" === 4)как ложно.

Triple-equal также работает немного быстрее, потому что JavaScript не должен тратить время на преобразование каких-либо типов, прежде чем дать вам ответ.

JSLint намеренно нацелен на то, чтобы сделать ваш код JavaScript как можно более строгим с целью уменьшения неясных ошибок. Он выделяет подобные вещи, чтобы попытаться заставить вас кодировать таким образом, чтобы вы уважали типы данных.

Но преимущество JSLint в том, что это просто руководство. Как говорят на сайте, это обидит вас, даже если вы очень хороший программист на JavaScript. Но вы не должны чувствовать себя обязанным следовать его совету. Если вы прочитали то, что в нем говорится, и вы это понимаете, но уверены, что ваш код не сломается, то вы не обязаны что-либо менять.

Вы даже можете указать JSLint игнорировать категории проверок, если вы не хотите, чтобы вас засыпали предупреждениями, с которыми вы ничего не собираетесь делать.

Spudley
источник
3
Я не спрашивал «Что такое ===», поэтому я не уверен, почему вы на него ответили.
Metropolis
8
@Metropolis: если по другой причине, то в качестве фона на случай, если кто-то еще прочитает ответ, который не знает. Тем не менее, я попытался ответить на ваш вопрос в следующих абзацах.
Spudley
@Spudley +1 за дополнительную и полезную информацию
Ben Junior
1
да, это в 10-100 раз быстрее: jsperf speed test
владкрас
8

Цитата из http://javascript.crockford.com/code.html :

=== и! == Операторы.

Почти всегда лучше использовать операторы === и! ==. Операторы == и! = Выполняют приведение типов. В частности, не используйте == для сравнения с ложными значениями.

JSLint очень строгий, их 'webjslint.js' даже не проходит их собственную проверку.

Lekensteyn
источник
Хорошее разъяснение. Это правда, насчет webjslint.jsотсутствия проверки - хотя большинство ошибок, которые я вижу сейчас, связаны с интервалом. Очевидно, что при рассмотрении JavaScript с использованием JSLint необходимо руководствоваться здравым смыслом и разумным суждением.
hotshot309
Использование этого слова alwaysавтоматически лишает эту цитату мудрости. Умные программисты не догматичны. Они используют то, что лучше всего в данной ситуации. И они приветствуют и используют любой инструмент, встроенный в самое ядро ​​языка, а не просто отвергают его с помощью just never touch it. Итог: мой код короче (и не только из-за сохранения одного =символа), поэтому мой сайт загружается быстрее, с меньшими затратами на пропускную способность, поэтому мой пользователь лучше обслуживается.
Stijn de Witt
4

Если хотите проверить на фальшивость. JSLint не позволяет

if (foo == null)

но позволяет

if (!foo)
nano2nd
источник
Используйте то ===, что рекомендует JSLint.
clickbait
1
@NarawaGames Это решение вполне приемлемо.
Это плохой ответ. Дело в том, что оба они означают другое. foo == nullпроверяет наличие null или undefined. !fooпроверяет наличие null, undefined, 0 и пустой строки.
Markos
@Markos Этот ответ призван быть полезной альтернативой, чтобы сделать JSLint счастливым и сохранить логику вашего кода нетронутой, а не быть точным эквивалентом. Вот почему я поставил перед ответом префикс «Если проверяю на ложность»
nano2nd 01
3

Чтобы помочь объяснить этот вопрос, а также объяснить, почему NetBeans (из) 7.3 начал показывать это предупреждение, это отрывок из ответа на трекере ошибок NetBeans, когда кто-то сообщил об этом как об ошибке:

Рекомендуется использовать === вместо == в JavaScript.

Операторы == и! = Выполняют приведение типов перед сравнением. Это плохо, потому что приводит к истинному значению '\ t \ r \ n' == 0. Это может замаскировать типовые ошибки. JSLint не может надежно определить, правильно ли используется ==, поэтому лучше вообще не использовать == и! = И всегда использовать вместо них более надежные операторы === и! ==.

Справка

EM-Creations
источник
1
Я обнаружил эту ошибку только сейчас, используя Netbeans. Странно, что они отнеслись к этому с серьезностью предупреждения из-за приведенного ими странного примера.
omikes
1
я имею в виду, это правда, но есть много случаев использования, в которых человек знает, что две сравниваемые вещи будут одного типа, поэтому кажется странным, что из-за этого странного случая, когда возврат каретки может сравниваться с числом ноль - причина того, что все использования == считаются неправильными. Я обнаружил, что === работает быстрее, поскольку преобразования типов не выполняются. Я удивлен, что не узнал этого до netbeans.
omikes
@oMiKeY Да, я понимаю, что вы имеете в виду, они могли бы привести более реалистичные примеры!
EM-Creations
2

На самом деле это не может вызвать проблем, это просто совет. Возьми это или оставь. Тем не менее, я не уверен, насколько это умно. Вполне могут быть контексты, в которых это не представляет собой проблему.

Рушио
источник
1
но почему используется слово «ожидаемый»? Это звучит так, будто вы всегда должны это делать.
Metropolis
4
Оценщик ищет верный ответ, пытаясь его проверить. Если он не получил правильного ответа, значит, он не ожидал. Валидатор начинает с предположения, что все в порядке, а затем указывает на ошибки при прохождении кода. Он не обязательно понимает, что является недопустимым ответом, он просто знает, когда видит недопустимый. Он также может работать в обратном направлении, сознательно ища плохой код в соответствии с правилами того, что плохо. Белый список против черного списка.
Rushyo
Вопрос был «Есть ли в этом смысл?». Учитывая этот вопрос, да, это так. Кроме того, это было пять лет назад . Иисус.
Rushyo