boolean w instrukcji if

144

Dzisiaj dostałem uwagę na temat kodu, biorąc pod uwagę sposób, w jaki sprawdzam, czy zmienna jest prawdziwa, czy fałszywa w zadaniu szkolnym.

Kod, który napisałem, wyglądał mniej więcej tak:

var booleanValue = true;

function someFunction(){
    if(booleanValue === true){
        return "something";
    }
}

Powiedzieli, że lepiej / schludniej napisać to w ten sposób:

var booleanValue = true;

function someFunction(){
    if(booleanValue){
        return "something";
    }
}

Uwaga, którą otrzymałem na temat części „=== prawda” była taka, że ​​nie jest ona potrzebna i może powodować zamieszanie.

Jednak moim pomysłem jest to, że lepiej jest sprawdzić, czy zmienna jest logiczna, czy nie, zwłaszcza, że ​​JavaScript jest językiem o luźnym typie.

W drugim przykładzie łańcuch również zwróciłby „coś”;

Więc moje pytanie; Czy w przyszłości lepiej jest stracić część „=== true”, czy też dobrą praktyką jest sprawdzenie również typu zmiennej.

Edycja: W moim „prawdziwym” kodzie wartość logiczna reprezentuje, czy obraz został usunięty, czy nie, więc jedyne wartości, które powinna mieć wartość boolValue, to true lub false.

Na przykład 0 i 1 nie powinny znajdować się w tej zmiennej.

DirkZz
źródło
4
jest czytelny i dobrą praktyką jest użycie ===
Piyas De
2
+1 dla === true. Pozwala uniknąć nieporozumień !!
gashu
1
@gashu Consider [0] === trueocenia jako fałsz.
RestingRobot
1
@Jlange nie powinno? Proszę wyjaśnić
gashu
Miałem na myśli to, że jeśli chciałbyś po prostu sprawdzić, czy istnieje „prawda”, to stwierdzenie nie powiedzie się, nawet jeśli powinno zostać ocenione jako prawda ([0] zwraca wartość prawda, ale nie bez konwersji typu). To naprawdę zależy od tego, co próbujesz osiągnąć za pomocą swojego oświadczenia. Użyj, === truegdy musisz upewnić się, że warunek jest dokładnie równy true.
RestingRobot

Odpowiedzi:

222

Po pierwsze, fakty:

if (booleanValue)

Zaspokoi ifoświadczenie o dowolnej wartości truthy z booleanValuetym true, każda niezerowa liczba, każdy niepusty ciąg znaków, dowolny obiekt lub tablica referencyjna, itd ...

Z drugiej strony:

if (booleanValue === true)

Spowoduje to spełnienie ifwarunku tylko wtedy, gdy booleanValuejest dokładnie równe true. Żadna inna prawdziwa wartość tego nie zadowoli.

Z drugiej strony, jeśli to zrobisz:

if (someVar == true)

Następnie JavaScript wykona wpisanie przymusu, trueaby dopasować typ, someVara następnie porównać dwie zmienne. Jest wiele sytuacji, w których prawdopodobnie nie jest to zamierzone. Z tego powodu w większości przypadków chcesz tego uniknąć, ==ponieważ istnieje dość długi zestaw reguł dotyczących tego, w jaki sposób JavaScript wymusza dwie rzeczy, aby były tego samego typu, chyba że rozumiesz wszystkie te zasady i możesz przewidzieć wszystko, co interpreter JS może zrobić, gdy biorąc pod uwagę dwa różne typy (których większość programistów JS nie potrafi), prawdopodobnie chcesz ==całkowicie uniknąć .

Jako przykład tego, jak zagmatwany może być:

var x;

x = 0;
console.log(x == true);   // false, as expected
console.log(x == false);  // true as expected

x = 1;
console.log(x == true);   // true, as expected
console.log(x == false);  // false as expected

x = 2;
console.log(x == true);   // false, ??
console.log(x == false);  // false 

Jeśli chodzi o wartość 2, można by pomyśleć, że 2jest to prawdziwa wartość, więc można by ją porównać korzystnie true, ale nie tak działa wymuszanie typu. Konwertuje wartość prawej ręki, aby dopasować typ wartości lewej ręki, więc konwertuje trueją na liczbę, 1więc porównuje, 2 == 1co z pewnością nie jest tym, co prawdopodobnie zamierzałeś.

Więc strzeż się kupującego. Prawdopodobnie najlepiej jest tego unikać ==w prawie wszystkich przypadkach, chyba że dokładnie znasz typy, które będziesz porównywać, i wiesz, jak działają wszystkie możliwe algorytmy wymuszania typów.


Tak więc naprawdę zależy to od oczekiwanych wartości booleanValuei sposobu działania kodu. Jeśli wiesz z góry, że będzie miał tylko wartość a truelub false, porównaj ją jawnie z

if (booleanValue === true)

to tylko dodatkowy kod i niepotrzebne i

if (booleanValue)

jest bardziej kompaktowy i prawdopodobnie czystszy / lepszy.

Jeśli z drugiej strony nie wiesz, co booleanValuemoże być i chcesz sprawdzić, czy jest naprawdę ustawiona na truebez innych automatycznych konwersji typów, to

if (booleanValue === true)

to nie tylko dobry pomysł, ale wymagany.


Na przykład, jeśli spojrzysz na implementację .on()w jQuery, ma ona opcjonalną wartość zwracaną. Jeśli wywołanie zwrotne powróci false, jQuery automatycznie zatrzyma propagację zdarzenia. W tym konkretnym przypadku, ponieważ jQuery chce propagacji zatrzymują się tylko jeśli falsezostał zwrócony, sprawdzić ich wartość zwracana explicity za === falsebo nie chcą undefinedlub 0lub ""lub cokolwiek innego, co spowoduje automatyczne typu nawróconego false aby również spełniać porównanie.

Na przykład, oto kod wywołania zwrotnego obsługi zdarzenia jQuery:

ret = ( specialHandle || handleObj.handler ).apply( matched.elem, args );

if ( ret !== undefined ) {
     event.result = ret;
     if ( ret === false ) {
         event.preventDefault();
         event.stopPropagation();
     }
 }

Widać, że jQuery wprost szuka ret === false.

Ale jest też wiele innych miejsc w kodzie jQuery, w których prostsze sprawdzenie jest właściwe, biorąc pod uwagę pożądany kod. Na przykład:

// The DOM ready check for Internet Explorer
function doScrollCheck() {
    if ( jQuery.isReady ) {
        return;
    }
    ...
jfriend00
źródło
Od dłuższego czasu zastanawiałem się nad tym pytaniem, ale nie miałem szansy znaleźć nikogo, kogo mógłbym zapytać. Byłbym wdzięczny, gdybyś mógł rzucić okiem. stackoverflow.com/questions/32615466/ ...
mmm
Ta odpowiedź nie jest całkowicie poprawna. „x == true” nie będzie prawdziwe dla liczb niezerowych.
Teemoh
@Teemoh - nie rozumiem twojego komentarza. Zobacz jsfiddle.net/jfriend00/89h8d8tm .
jfriend00
1
Chcę tylko powiedzieć, że „if (x)” to nie to samo, co „if (x == true)”, jak napisałeś w pierwszym akapicie swojej odpowiedzi. „if (x)” jawnie konwertuje „x” na jego logiczną reprezentację. „if (x == true)” użyje algorytmu porównania abstrakcyjnego EcmaScript. Napisałeś, że 'if (x == true)' będzie prawdziwe dla dowolnej liczby niezerowej, niepustego łańcucha lub dowolnego obiektu. To jest po prostu złe. Jeśli uruchomię twój przykład z 2 zamiast 1, to nie zadziała.
Teemoh
2
@Teemoh - rozumiem twój punkt widzenia. Odpowiedź poprawiona i doprecyzowana. Dodałem sekcję dotyczącą wymuszania typów z przykładem, który pokazuje, jak może on zrobić nieoczekiwane rzeczy.
jfriend00
40

Jeśli napiszesz if(x === true):, Będzie to prawda tylko dla x = prawda

Jeśli napiszesz if(x):, będzie prawdziwe dla każdego x, które nie jest: '' (pusty łańcuch), false, null, undefined, 0, NaN.

karaxuna
źródło
(pusty ciąg), false, null, undefined, 0, NaN
Oliboy50
Nie zapomnij NaNi -0.
Haykam
8

W zwykłym "if" zmienna zostanie przekształcona na wartość logiczną i używa toBoolean na obiekcie: -

    Argument Type   Result

    Undefined       false
    Null            false
    Boolean         The result equals the input argument (no conversion).
    Number          The result is false if the argument is +0, 0, or NaN;
                    otherwise the result is true.
    String          The result is false if the argument is the empty 
                    String (its length is zero); otherwise the result is true.
    Object          true.

Ale porównanie z === nie ma żadnego typu przymusu, więc muszą być równe bez przymusu.

Jeśli mówisz, że obiekt może nawet nie być wartością logiczną, być może będziesz musiał rozważyć więcej niż tylko prawda / fałsz.

if(x===true){
...
} else if(x===false){
....
} else {
....
}
QuentinUK
źródło
5

To zależy od twojego przypadku. Może być sensowne sprawdzenie typu, ale jeśli jest to tylko flaga, tak nie jest.

Ven
źródło
===Porównanie nie wykonuje typu przymus. Zatem kod OP skutecznie testuje typ flagi. Udaje się tylko wtedy, gdy wartość jest wartością logiczną i jest prawdziwa.
Jesse Hallett
Pozwólcie, że przeredaguję Jeśli wiesz, że to będzie prawda lub fałsz, to nie ma znaczenia.
Ven
5

Ogólnie rzecz biorąc, łatwiej jest pominąć rozszerzenie === true.

Jednak w Javascript te stwierdzenia są inne.

if (booleanValue)wykona jeśli booleanValuejest truthy - coś innego niż 0, false, '', NaN, null, i undefined.

if (booleanValue === true)wykona tylko wtedy, gdy booleanValuejest dokładnie równe true.

SLaks
źródło
Właśnie tego chcę być pewien, nawet jeśli chcę, aby wartość boolValue była prawdziwa lub fałszywa. Zmienna jest wielokrotnie ustawiana na wartość true / false w kodzie. Wiem o tym, kiedy piszę kod, ale jeśli ponownie sprawdzę kod rok później, to po prostu wielki znak zapytania, chyba że wszystko ponownie przeczytam, prawda?
DirkZz
@aldanux: Ups; Miałem na myśli ''.
SLaks
4

(===)Operator tożsamości zachowuje się identycznie jak (==)operator równości , z wyjątkiem tego, że nie jest wykonywana żadna konwersja typów, a typy muszą być takie same, aby były uznawane za równe.

OPROGRAMOWANIE Apollo
źródło
Twoje ostatnie zdanie jest błędne. Spróbować swoich dwóch sprawozdań if (booleanValue)i if (booleanValue==true)kiedy booleanValuejest 2. Te dwa stwierdzenia nie dają tego samego wyniku.
jfriend00
Ciekawy. Wierzę ci na słowo. Myślałem w świecie ObjC / C / C ++, w JS zakładam, że masz rację, ponieważ typy danych w JS można zmieniać, a 2 == true nie kwantyfikuje jeśli wtedy.
OPROGRAMOWANIE Apollo
1
Zobacz moją odpowiedź powyżej na ten konkretny przykład. Ma to związek z tym, jak JavaScript dokonuje automatycznej konwersji typów w celu porównania dwóch wartości różnych typów.
jfriend00
3

Ponieważ zaznaczona wartość jest Booleanpreferowana, zaleca się użycie jej bezpośrednio w celu zmniejszenia kodowania iw ogóle zrobiło to samo==true

Alyafey
źródło
2

Ponieważ już zainicjowałeś wyraźnie jako bool, myślę, że ===operator nie jest wymagany.

Słoneczny
źródło
2

Jeśli zmienna może zawsze przyjmować tylko wartości logiczne, rozsądne jest użycie krótszej składni.

Jeśli może potencjalnie być przypisane inne typy, a trzeba odróżnić trueod 1lub "foo", następnie należy użyć === true.

Barmar
źródło
2

Myślę, że twoje rozumowanie jest rozsądne. Jednak w praktyce stwierdziłem, że znacznie częściej pomija się ===porównanie. Myślę, że są ku temu trzy powody:

  1. Zwykle nie dodaje to znaczenia wyrażeniu - tak jest w przypadkach, gdy wiadomo, że wartość jest logiczna.
  2. Ponieważ w JavaScript występuje duża niepewność typu, wymuszenie sprawdzenia typu zwykle gryzie Cię, gdy pojawia się nieoczekiwana wartość undefinedlub nullwartość. Często chcesz po prostu, aby test zakończył się niepowodzeniem w takich przypadkach. (Chociaż staram się zrównoważyć ten pogląd hasłem „szybko przegrywaj”).
  3. Programiści JavaScript lubią szybko bawić się typami - szczególnie w wyrażeniach boolowskich - ponieważ możemy.

Rozważmy ten przykład:

var someString = getInput();
var normalized = someString && trim(someString);  
// trim() removes leading and trailing whitespace

if (normalized) {
    submitInput(normalized);
}

Myślę, że tego rodzaju kod nie jest rzadkością. Zajmuje się przypadki, w których getInput()powraca undefined, nulllub pusty ciąg. Ze względu na dwie wartości logiczne submitInput()jest wywoływana tylko wtedy, gdy dane wejście jest łańcuchem zawierającym znaki inne niż białe znaki.

W JavaScript &&zwraca swój pierwszy argument, jeśli jest fałszywy, lub drugi argument, jeśli pierwszy argument jest prawdziwy; tak normalizedbędzie, undefinedjeśli someStringbyło nieokreślone i tak dalej. Oznacza to, że żadne dane wejściowe do powyższych wyrażeń logicznych nie są w rzeczywistości wartościami logicznymi.

Wiem, że wielu programistów, którzy są przyzwyczajeni do silnego sprawdzania typów, wzdraga się, widząc taki kod. Ale uwaga, stosowanie silnego pisania prawdopodobnie wymagałoby jawnych sprawdzeń dla nulllub undefinedwartości, co zagraciłoby kod. W JavaScript nie jest to potrzebne.

Jesse Hallett
źródło
1

To zależy. Jeśli obawiasz się, że twoja zmienna może skończyć się jako coś, co zostanie rozwiązane jako PRAWDA. Wtedy twarde sprawdzenie jest koniecznością. W przeciwnym razie to zależy od Ciebie. Jednak wątpię, czy składnia whatever == TRUEkiedykolwiek zmyliłaby każdego, kto wiedział, co robią.

usumoio
źródło
1

W Javascript idea boolean jest dość niejednoznaczna. Rozważ to:

 var bool = 0 
 if(bool){..} //evaluates to false

 if(//uninitialized var) //evaluates to false

Więc kiedy używasz instrukcji if (lub jakiejkolwiek innej instrukcji sterującej), nie musisz używać zmiennej typu „boolean”. Dlatego moim zdaniem część "=== prawda" twojego stwierdzenia jest niepotrzebna, jeśli wiesz, że jest to wartość logiczna, ale jest absolutnie konieczna, jeśli twoja wartość jest niejednoznaczną zmienną "prawdziwą". Więcej na temat wartości logicznych w javscript można znaleźć tutaj .

OdpoczynekRobot
źródło
1

Można również przetestować za pomocą obiektu Boolean, jeśli chcesz przetestować obiekt error={Boolean(errors.email)}

Igor Pavlenko
źródło