JSLint очікується '===', а замість цього побачить '=='


90

Нещодавно я запускав частину свого коду через JSLint, коли прийшов із цією помилкою. Однак, на мою думку, смішно щодо цієї помилки полягає в тому, що вона автоматично передбачає, що все == має бути ===.

Чи справді це має якийсь сенс? Я бачив багато випадків, коли ви не хотіли б порівнювати тип, і я переживаю, що це насправді може спричинити проблеми.

Слово "очікуваний" означатиме, що це слід робити КОЖИЙ раз ..... Це те, що для мене не має сенсу.


7
Я теж натрапив на це з JSLint. Я зробив оновлення з == до ===, і це насправді зламало раніше працюючий код.
kemiller2002

5
Якщо ваш код має більше 100 рядків, він не передаватиме jslint, насправді це неможливо.

3
"Зламаний" - занадто сильне слово. Це змінило значення вашого коду. Якщо ви робили myVar == nullперевірку, так, великі зміни. ; ^) Аргумент Крокфорда полягає в тому, що він зробив значення коду більш точним, і з цим важко сперечатися.
jorffin

Відповіді:


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 == 'це рядок' - ваш код, ймовірно, має більші проблеми, ніж подвійна рівність! Якщо ви точно знаєте, з якими типами ви маєте справу, і знаєте, як саме вони взаємодіють з ==, то, думаю, вам слід це використовувати.
Джон

3
@Jon Суть ===оператора - це чіткість коду. Немає розумної ситуації для використання, ==оскільки вона ніколи не буде такою чіткою та зрозумілою, як оператор ідентифікації. Справа не в тому, розумієте ви операторів чи ні, а в тому, щоб використовувати той, який полегшує читання вашого коду майже без будь-яких витрат. Єдині розробники, які сперечаються проти оператора ідентичності, - це сольні розробники та люди, які не працюють у командах. За визначенням, люди, коди яких переглядаються, не переглядаються достатньою кількістю очей.
Alternatex

2
Я вважаю, що порівняння == null є майже важливим. Проблема стає ще менш важливою, якщо ваш код добре перевірений.
Джон

1
Насправді бувають випадки, коли використання == є необхідним для виконання необхідного тесту. якщо foo.toString () буде виконуватись передбачувано, а звичайний рядок потрібно перевірити на відповідний результат, тоді написання foo == stringToTest набагато чистіше, ніж foo.toString () === stringToTest.
Кріспен Сміт,

2
@Alternatex Якби суть полягала в ясності, вони не повинні були зробити це TRIPLE рівним! Жоден новачок цього не розуміє. Щонайменше подвійне рівне відомо з інших мов. Крім того, there is no reasonable situationє грубим викривленням. Подумайте про (рідні) типи Javascript Numberта String. Їх існування доводить, що автори Javascript мали на увазі певні випадки використання ==. Ви справді вважаєте, що new String('hi') === 'hi'оцінка до falseдуже зрозуміла? Будь ласка, напишіть фрагмент коду, який перевіряє ваш аргумент функції проти 'hi'прийняття як рядка, так і рядка, і скажіть мені, що це зрозуміло.
Stijn de Witt

25

JSLint за своєю суттю є більш захисним, ніж дозволяє синтаксис Javascript.

З документації JSLint:

Оператори ==and !=виконують примусовий тип перед порівнянням. Це погано, тому що це викликає ' \t\r\n' == 0істину. Це може замаскувати помилки типу.

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

Якщо ви тільки піклуватися про те , що значення truthy або falsy , а потім використовувати скорочену форму. Замість

(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-jednak також працює трохи швидше, тому що JavaScript не повинен витрачати час на будь-які перетворення типів, перш ніж дати вам відповідь.

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

Але хороша річ у JSLint полягає в тому, що це лише керівництво. Як кажуть на сайті, це зашкодить вашим почуттям, навіть якщо ви дуже хороший програміст JavaScript. Але ви не повинні почуватись зобов'язаними слідувати його порадам. Якщо ви прочитали, що там сказано, і розумієте, але впевнені, що ваш код не зламається, тоді вас не змушують щось змінювати.

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


3
Я не запитував "Що таке ===", тому я не впевнений, чому ви відповіли на нього.
Метрополіс,

8
@Metropolis: якщо ні з якої іншої причини, то як передумова, якщо хтось інший прочитає відповідь, хто не знав. Однак після цього я намагався відповісти на ваше запитання в абзацах.
Spudley

@Spudley + 1 для отримання додаткової та корисної інформації
Ben Junior

1
так, це в 10-100 разів швидше: тест швидкості
jsperf

8

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

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

Майже завжди краще використовувати оператори === та! ==. Оператори == та! = Виконують примус типу. Зокрема, не використовуйте == для порівняння проти хибних значень.

JSLint дуже суворий, їх 'webjslint.js' навіть не проходить власну перевірку.


Приємне роз’яснення. Це правда, щодо webjslint.jsнеперевірки - хоча більшість помилок, які я бачу зараз, пов’язані з інтервалами. Зрозуміло, при перегляді JavaScript за допомогою JSLint потрібно використовувати здоровий глузд та розумне судження.
hotshot309

Використання цього слова alwaysавтоматично дискваліфікує цю цитату як мудрість. Розумні програмісти не є догматичними. Вони використовують те, що найкраще в даній ситуації. І вони вітають і охоплюють будь-який інструмент, вбудований в саму суть мови, а не просто відкидають його за допомогою just never touch it. Підсумок: мій код коротший (і не лише завдяки збереженню одного =символу), отже, мій сайт завантажується швидше, з меншими витратами на пропускну здатність, таким чином, моєму користувачеві краще обслуговувати.
Stijn de Witt

4

Якщо ви хочете перевірити на хибність. JSLint не дозволяє

if (foo == null)

але дозволяє

if (!foo)

Використовуйте ===, що рекомендує JSLint.
clickbait

1
@NarawaGames Це рішення є цілком прийнятним.

Ця відповідь не є доброю. Річ у тім, що обидва вони означають щось інше. foo == nullперевіряє на нуль або невизначено. !fooперевіряє наявність нульового, невизначеного, 0 та порожнього рядка.
Маркос

@Markos Ця відповідь має бути корисною альтернативою зробити JSLint щасливим і зберегти логіку коду цілою, а не бути точним еквівалентом. Ось чому я відповів префіксом "Якщо перевіряю хибність"
nano2

3

Щоб допомогти пояснити це питання, а також пояснити, чому NetBeans (з) 7.3 почав показувати це попередження, це витяг із відповіді на відстежувач помилок NetBeans, коли хтось повідомив про це як про помилку:

Рекомендується використовувати ===, а не == в JavaScript.

Оператори == та! = Виконують примусовий тип перед порівнянням. Це погано, оскільки спричиняє істину '\ t \ r \ n' == 0. Це може замаскувати помилки типу. JSLint не може надійно визначити, чи == використовується правильно, тому найкраще взагалі не використовувати == та! = І замість цього завжди використовувати надійніші оператори === та! ==.

Довідково


1
Я виявив цю помилку зараз, використовуючи також Netbeans. Дивно, що вони поставились би до цього із суворою суворістю через химерний приклад, який вони подали.
omikes

1
я маю на увазі, що це правда, але є багато випадків використання, коли людина знає, що дві порівняні речі будуть одного типу, тому здається дивним, що через цей дивний випадок, коли повернення каретки можна порівняти з кількістю нуль - причина, через яку всі звички == вважаються помилковими. Я з'ясовую, що === все-таки швидше, оскільки ніяких перетворень типів не робиться. я здивований, що не дізнався про це раніше, ніж netbeans.
omikes

@oMiKeY Так, я розумію, що ти маєш на увазі, вони могли б навести більш реалістичні приклади!
EM-Creations

2

Ну, насправді це не може викликати проблем, це просто надання вам поради. Прийняти його або залишити його. Тим не менш, я не впевнений, наскільки це розумно. Цілком можуть бути контексти, в яких це не представляє це як проблему.


1
але чому вживається слово "очікуваний"? З-за цього здається, що ви завжди повинні це робити.
Метрополіс,

4
Оцінювач шукає дійсну відповідь, оскільки намагається перевірити її. Якщо він не отримає дійсну відповідь, то це не те, що він очікував. Валідатор починається з припущення, що все в порядку, а потім вказує на помилки під час обходу коду. Він не обов'язково розуміє, що таке недійсна відповідь, він просто знає, коли бачить недійсну відповідь. Це також може працювати в зворотному напрямку, навмисно шукаючи поганий код відповідно до правил поганого. Білий чи чорний списки.
Rushyo

Питання було "Чи справді це має сенс?". Враховуючи це запитання, так, воно є. Крім того, це було п’ять років тому . Ісусе.
Rushyo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.