JSLint Oczekiwano „===”, a zamiast tego zobaczył „==”

90

Ostatnio uruchamiałem część mojego kodu przez JSLint, kiedy wpadłem na ten błąd. Uważam jednak, że zabawne w tym błędzie jest to, że automatycznie zakłada, że ​​all == powinno być ===.

Czy to naprawdę ma sens? Widziałem wiele przypadków, w których nie chciałbyś porównywać typów i obawiam się, że może to faktycznie powodować problemy.

Słowo „Oczekiwany” sugerowałoby, że powinno się to robić KAŻDY raz ..... To nie ma dla mnie sensu.

Metropolia
źródło
7
Natknąłem się też na to z JSLint. Dokonałem aktualizacji z == do === i faktycznie zepsuło to poprzednio działający kod.
kemiller2002
5
Jeśli twój kod ma więcej niż 100 linii, nie przejdzie przez jslint, naprawdę jest to niemożliwe.
3
„Spłukany” to zbyt mocne słowo. Zmieniło to znaczenie twojego kodu. Jeśli robiłeś myVar == nullczek, tak, duże zmiany. ; ^) Argument Crockforda jest taki, że uściślił znaczenie kodu i trudno się z tym spierać.
ruffin

Odpowiedzi:

127

IMO, używanie na ślepo ===, bez próby zrozumienia, jak działa konwersja typów , nie ma większego sensu.

Główna obawa związana z operatorem Equals ==polega na tym, że reguły porównania w zależności od porównywanych typów mogą sprawić, że operator będzie nieprzechodni, na przykład, jeśli:

A == B AND
B == C

Naprawdę nie gwarantuje, że:

A == C

Na przykład:

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

Operator Strict Equals ===nie jest konieczny, gdy porównujesz wartości tego samego typu, najczęstszy przykład:

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

Porównujemy wynik typeofoperatora, który zawsze jest ciągiem , z literałem ciągu ...

Lub kiedy znasz reguły wymuszania typów, na przykład sprawdź, czy coś jest, nullczy undefinedcoś:

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ó
źródło
1
Nienawidzę tej zasady JSLint. Myślę, że prawdziwym problemem jest to, że ludzie nie powinni używać operatorów w sposób, którego nie rozumieją (jak na ironię są to często ludzie tego samego rodzaju, którzy ślepo zastępują „===” przez „==”). Jasne, istnieje kilka typowych przypadków, które pojawiają się podczas porównywania liczby 0 z różnymi ciągami, ale jeśli porównujesz niepowiązane dane, takie jak 0 == „to jest ciąg znaków” - Twój kod prawdopodobnie ma większe problemy niż podwójne równe! Jeśli wiesz na pewno, z jakimi typami masz do czynienia i wiesz, jak dokładnie wchodzą w interakcję z ==, to myślę, że powinieneś go użyć.
Jon
3
@Jon Celem ===operatora jest przejrzystość kodu. Nie ma rozsądnej sytuacji do wykorzystania, ==ponieważ nigdy nie będzie ona tak jasna i zrozumiała jak operator tożsamości. Nie chodzi o to, czy rozumiesz operatory, czy nie, chodzi o użycie tego, który sprawia, że ​​twój kod jest łatwiejszy do odczytania prawie bez żadnych kosztów. Jedynymi programistami, którzy spierają się przeciwko operatorowi tożsamości, są programiści indywidualni i osoby, które nie pracują w zespołach. Z definicji ludzie, których kod nie jest sprawdzany przez wystarczającą liczbę oczu.
Alternatex
2
Uważam, że porównanie == null jest prawie niezbędne. Problem staje się jeszcze mniej ważny, jeśli kod jest dobrze przetestowany.
Jon
1
W rzeczywistości istnieją sytuacje, w których użycie == jest niezbędne do wykonania wymaganego testu. Jeśli foo.toString () będzie działać w przewidywalny sposób i zwykły łańcuch musi zostać przetestowany pod kątem tego wyjścia, to zapis foo == stringToTest jest o wiele czystszy niż foo.toString () === stringToTest.
Crispen Smith
2
@Alternatex Gdyby chodziło o jasność, nie powinni byli robić tego POTRÓJNIE równa się! Żaden początkujący tego nie rozumie. Co najmniej podwójne równe jest znane z innych języków. Ponadto there is no reasonable situationjest to rażące zniekształcenie. Pomyśl o (natywnych) typach JavaScript Numberi String. Ich istnienie dowodzi, że autorzy JavaScript mieli na myśli określone przypadki użycia ==. Czy naprawdę uważasz, że new String('hi') === 'hi'ocenianie falsejest bardzo jasne? Napisz fragment kodu, który przetestuje argument funkcji pod kątem 'hi'akceptacji zarówno ciągu, jak i ciągu, i powiedz mi, że jest to jasne.
Stijn de Witt
25

JSLint jest z natury bardziej defensywny, niż pozwala na to składnia JavaScript.

Z dokumentacji JSLint:

==I !=operatorzy zrobić rodzaj przymusu przed porównaniem. To jest złe, ponieważ powoduje, ' \t\r\n' == 0że jest prawdą. Może to maskować błędy typu.

Porównując z dowolną z poniższych wartości, użyj operatorów ===lub !==(które nie powodują wymuszenia):0 '' undefined null false true

Jeśli zależy Ci tylko na tym, aby wartość była prawdziwa lub fałszywa , użyj krótkiej formy. Zamiast

(foo != 0)

tylko powiedz

(foo)

i zamiast

(foo == 0)

mówić

(!foo)

===I !==preferowane są operatorzy.

Daniel Vandersluis
źródło
8
Muszę stwierdzić, że ludzie z JSLint pracują w jakiejś bardzo wysokiej wieży z kości słoniowej, z której nigdy się nie wydostają. Javascript został zaprojektowany do użytku z ==operatorem. ===Jest szczególnym przypadkiem ... JSLint próbuje się wydawać, używając ==jakoś się mylić ... Jednak, spróbuj tego: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. Typy pierwotne mają odpowiednie klasy, które je zastępują ( Number, String), a JavaScript zależy od ==operatora, aby porównać te naturalne.
Stijn de Witt
17

Pamiętaj, że JSLint narzuca jednej osobie wyobrażenie o tym, jaki powinien być dobry JavaScript. Nadal musisz kierować się zdrowym rozsądkiem przy wdrażaniu sugerowanych zmian.

Ogólnie rzecz biorąc, porównanie typu i wartości uczyni twój kod bezpieczniejszym (nie napotkasz nieoczekiwanego zachowania, gdy konwersja typów nie zrobi tego, co myślisz, że powinna).

Justin Niessner
źródło
4
Poza tym nie może być tak inteligentny jak programista. Po prostu działa na podstawie tego, że większość użytkowników wpada w błąd przez automatyczną konwersję typu nieodłączną od systemu (jak przemoc - „pomóż mi, jestem represjonowany!”)
Rudu
14

Potrójne równe różni się od podwójnie równe, ponieważ oprócz sprawdzenia, czy dwie strony mają tę samą wartość, potrójnie równe sprawdza również, czy są one tego samego typu danych.

Tak ("4" == 4)jest prawdą, podczas gdy ("4" === 4)jest fałszem.

Potrójne równe również działa nieco szybciej, ponieważ JavaScript nie musi tracić czasu na wykonywanie jakichkolwiek konwersji typów przed udzieleniem odpowiedzi.

JSLint celowo ma na celu uczynienie kodu JavaScript tak ścisłym, jak to tylko możliwe, w celu zmniejszenia liczby niejasnych błędów. Podkreśla tego rodzaju rzeczy, próbując nakłonić cię do kodowania w sposób, który zmusza cię do poszanowania typów danych.

Ale dobrą rzeczą w JSLint jest to, że jest to tylko przewodnik. Jak mówią na stronie, to zrani twoje uczucia, nawet jeśli jesteś bardzo dobrym programistą JavaScript. Ale nie powinieneś czuć się zobowiązany do przestrzegania jego rad. Jeśli przeczytałeś, co ma do powiedzenia i rozumiesz to, ale masz pewność, że Twój kod się nie zepsuje, nie ma na tobie żadnego przymusu, aby cokolwiek zmienić.

Możesz nawet powiedzieć JSLint, aby ignorował kategorie kontroli, jeśli nie chcesz być bombardowany ostrzeżeniami, z którymi nie zamierzasz nic robić.

Spudley
źródło
3
Nie pytałem „Co to jest ===”, więc nie jestem pewien, dlaczego na to odpowiedziałeś.
Metropolis
8
@Metropolis: jeśli nie ma innego powodu, to jako tło na wypadek, gdyby ktoś inny przeczytał odpowiedź i nie wiedział. Próbowałem jednak odpowiedzieć na twoje pytanie w kolejnych akapitach.
Spudley,
@Spudley + 1, aby uzyskać dodatkowe i przydatne informacje
Ben Junior,
1
tak, to 10-100 razy szybciej: test prędkości
jsperf
8

Cytat z http://javascript.crockford.com/code.html :

=== i! == Operatory.

Prawie zawsze lepiej jest używać operatorów === i! ==. Operatory == i! = Wymuszają wpisywanie. W szczególności nie używaj == do porównywania z fałszywymi wartościami.

JSLint jest bardzo rygorystyczny, ich „webjslint.js” nie przechodzi nawet własnej weryfikacji.

Lekensteyn
źródło
Niezłe wyjaśnienie. To prawdawebjslint.js nie sprawdzanie poprawności - chociaż większość błędów, które teraz widzę, dotyczy odstępów. Oczywiście podczas przeglądania JavaScript przy użyciu JSLint należy kierować się zdrowym rozsądkiem i rozsądkiem.
hotshot309
Użycie tego słowa alwaysautomatycznie dyskwalifikuje ten cytat jako mądrość. Sprytni programiści nie są dogmatyczni. Używają tego, co najlepsze w danej sytuacji. Z zadowoleniem przyjmują i przyjmują każde narzędzie wbudowane w sam rdzeń języka, a nie tylko odrzucają je za pomocą rozszerzenia just never touch it. Konkluzja: Mój kod jest krótszy (i to nie tylko dzięki zapisaniu jednego =znaku), więc moja strona ładuje się szybciej, przy mniejszych kosztach przepustowości, dzięki czemu mój użytkownik jest lepiej obsługiwany.
Stijn de Witt
4

Jeśli chcesz przetestować pod kątem fałszywości. JSLint nie pozwala

if (foo == null)

ale pozwala

if (!foo)
nano2nd
źródło
Użyj ===, które zaleca JSLint.
clickbait
1
@NarawaGames To rozwiązanie jest całkowicie do przyjęcia.
Ta odpowiedź nie jest dobra. Chodzi o to, że oba oznaczają coś innego. foo == nullsprawdza, czy nie ma wartości null lub undefined. !foosprawdza, czy nie ma null, undefined, 0 i pustego ciągu.
Markos
@Markos Ta odpowiedź ma być pomocną alternatywą, aby uszczęśliwić JSLint i zachować logikę kodu w nienaruszonym stanie, a nie być dokładnym odpowiednikiem. Dlatego właśnie poprzedziłem odpowiedź słowem „Jeśli sprawdzam, czy nie ma fałszu”
nano2nd
3

Aby pomóc wyjaśnić to pytanie, a także wyjaśnić, dlaczego NetBeans (from) 7.3 zaczął wyświetlać to ostrzeżenie, jest to wyciąg z odpowiedzi w narzędziu do śledzenia błędów NetBeans, gdy ktoś zgłosił to jako błąd:

Dobrą praktyką jest używanie === zamiast == w JavaScript.

Operatory == i! = Wymuszają wpisywanie przed porównaniem. To jest złe, ponieważ powoduje, że '\ t \ r \ n' == 0 jest prawdziwe. Może to maskować błędy typu. JSLint nie może wiarygodnie określić, czy == jest używane poprawnie, więc najlepiej w ogóle nie używać == i! = I zamiast tego zawsze używać bardziej niezawodnych operatorów === i! ==.

Odniesienie

Kreacje EM
źródło
1
Znalazłem ten błąd właśnie teraz przy użyciu Netbeans. Dziwne, że potraktowaliby to z ostrzeżeniem z powodu dziwacznego przykładu, który przedstawili.
omikes
1
mam na myśli, to prawda, ale jest wiele przypadków użycia, w których osoba wie, że dwie porównywane rzeczy będą tego samego typu, więc wydaje się dziwne, że z powodu tego dziwnego przypadku, w którym powrót karetki można porównać do liczby zero jest powodem, dla którego wszystkie zastosowania == są uważane za nieprawidłowe. Dowiaduję się jednak, że === jest szybsze, ponieważ nie są wykonywane żadne konwersje typów. jestem zaskoczony, że nie dowiedziałem się tego przed netbeanami.
omiki
@oMiKeY Tak, rozumiem, co masz na myśli, mogli podać bardziej realistyczne przykłady!
EM-Creations
2

Cóż, tak naprawdę nie może powodować problemów, po prostu daje rady. Zdecyduj sie. To powiedziawszy, nie jestem pewien, jakie to sprytne. Mogą istnieć konteksty, w których nie przedstawia tego jako problemu.

Rushyo
źródło
ale dlaczego używa się słowa „Oczekiwany”? To sprawia, że ​​brzmi to tak, jakbyś zawsze to robił.
Metropolis
4
Oceniający szuka prawidłowej odpowiedzi, ponieważ próbuje ją zweryfikować. Jeśli nie otrzyma prawidłowej odpowiedzi, to nie jest to, czego oczekiwał. Walidator zaczyna od założenia, że ​​wszystko jest w porządku, a następnie wskazuje błędy podczas przeglądania kodu. Niekoniecznie rozumie, czym jest nieprawidłowa odpowiedź, po prostu wie, kiedy widzi nieważną odpowiedź. Może również działać na odwrót, celowo wyszukując zły kod zgodnie z regułami tego, co jest złe. Biała lista a czarna lista.
Rushyo
Pytanie brzmiało: „Czy to naprawdę ma sens?”. Biorąc pod uwagę to pytanie, tak. Poza tym było to pięć lat temu . Jezus.
Rushyo