Rozważania na temat rzutowania typów

0
'' == '0'           // false - ma sens, bo '' jest falsy, a '0' jako string to true
0 == ''             // true - rowniez ma sens bo 0 jest falsy, tak samo jak ''
0 == '0'            // true - nie ma sensu bo 0 jest falsy, a string powinien byc traktowany jako true tak jak w pierwszym porownaniu

false == 'false'    // false - to samo co w pierwszym
false == '0'        // true - znowu bez sensu tak samo jak 0 == '0' 

false == undefined  // false bez sensu, undefined zachowuje sie jako falsy, a w porownaniu to nie to samo
false == null       // false - tak samo tutaj
null == undefined   // true - 2 razy falsy, wiec się zgadza, ale dlaczego 2 powyższe się zachowują w taki dziwny sposób?

Możemy używać ===. Tylko jest pewien problem. Jeżeli chcemy, żeby działało nam porównanie typu 0 == '', co ma sens (zgodnie z założeniami które wartości są falsy) to może to być zgubne. Zauważyłem, że jeżeli sami sobie skastujemy to na boolean a dopiero pozniej porównamy to zaczyna działać. Dlaczego jest taka rozbieżność?

// ! castuje na boolean, ale odwraca wartość, więc odwracamy ją jeszcze raz i robiąc !! otrzymujemy coś jak (boolean) zmienna

typeof !!'' // boolean
!!'' // false

!!'' == !!'0'         // false - ma sens, bo '' jest falsy, a '0' jako string to true i tak też jest castowane
!!0 == !!''             // true - rowniez ma sens bo 0 jest falsy, tak samo jak '' i tak też jest castowane
!!0 == !!'0'       // FALSE - zgadza się, bo !!'0' robi z tego true;

false == !!'false'    // false - każdy string to true, więc to samo tutaj się dzieje
false == !!'0'        // false - znowu to co wyżej 

false == !!undefined  // true - undefined jest falsy, wiec false == falsy => true i git
false == !!null       // j.w.
!!null == !!undefined   // true - 2 razy falsy, wiec się zgadza

Czyli stosowanie takiego porównania to taka pośrednia wersja pomiędzy ===, a ==. Pozwala na pewien luz (bo pokrywają się przykłady z 1 listingu) i nie daje takich bezsensownych nieprzewidywalnych wyników. Z drugiej strony wyglada to jak...

Naszła mnie jeszcze jedna myśl. Czy jeżeli porównujemy np. 0 == '0' to w tym wpadku string jest castowany najpierw na number, a później obydwa na boolean i zachodzi porównanie? Jeżeli tak faktycznie jest to może i się to zgadza, co nie zmienia faktu, że wychodzi na to, że w zależności od kontekstu użycia zmienna ma różną wartość boolowską Oo

TL:DR
Czyli reasumując te wypociny:
var x = '0';

  1. Jeżeli użyjemy zmiennej w samej na zasadzie if(x) to zgodnie z zasadami truthy/falsy x da true i sterowanie wejdzie do if'a.
  2. Jeżeli tą samą wartość porównamy z czymś to zachodzi rzutowanie tych typów w dół (zgodnie z tym jak te typy są rzutowane a nie truty/falsy), czyli jak mamy 0 i stringa to:
    a) 0 => boolean == false;
    b) '0' => number => 0 => boolean => 'false'
    i stąd się bierze 0=='0' == true.
  3. Sposób podany przeze mnie wyżej wymusza podczas porównania korzystanie z zasady truthy falsy

Zgadza się? :D

1

Przy porównaniu '0' == false obie strony zostają zamienione na typ liczbowy. Z '0' robi się 0, tak samo jak z false robi się 0.
Jeżeli weźmiemy nasze '0' i wrzucimy w ifa dostaniemy true - bo string nie jest pusty.

Przy używaniu double not (!!) otrzymujemy booleana, nie coś jak.

@Edit:
przeczytałem długą wersję, błędy w rozumowaniu:
`` == '0' // false - ma sens, bo jest falsy, a '0' jako string to true
Nie do końca. Masz przecież dwa stringi o różnej zawartości :)
Wszystko zależy od tego co z czym porównujesz.
0 == '0' // true - nie ma sensu bo 0 jest falsy, a string powinien byc traktowany jako true tak jak w pierwszym porownaniu
true bo zostanie to porównane jako '0' == '0', ma sens? :)

Na MDN pewnie będą jakieś wywody na temat tego co, jak i dlaczego tak się porównuje.

0

A widzisz ja byłem przekonany ze wartości są zbijane do boolean a tu się okazuje ze w zależności co z czym porównujemy to odbywa się rożna konwersja lub wcale jak w przypadku porównania dwóch stringów. Ja myślałem ze robi się z tego boola. Dobrze mowię?

1

Warto poczytać: https://github.com/getify/You-Dont-Know-JS/blob/master/types%20&%20grammar/ch4.md oraz Effective JavaScript jeśli chcesz zrozumieć w pełni temat. Całkiem fajne wystąpienie:

0

Dopiero to znalazłem i trochę mi się rozjaśniło polecam każdemu tą tabelkę https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

1

Ja polecam nie stosować operatora == ;) Bo potem Ty wiesz, a ktoś nie wie i namiesza, a potem Ty zapomnisz i coś pomieszasz, a potem ktoś inny jeszcze coś poprawi - i kod pełen bugów gotowy ;)

0

Czyli jak np. mam stringa "true" i wiem, że tam jest na 100% string to co w takim wypadku zrobić? Albo mam wartości 0|1 do porównania, bo powiedzmy w bazie jest deleted 0|1 albo cokolwiek innego.

var x = "0";
if(x === "0") //zrob cos tam
1

Nie jestem fanem unikania czegokolwiek w kodzie z powodu "ktoś nie wie i namiesza". Ktoś kto nie zauważy różnicy pomiędzy == i === nie powinien pracować z js.

@Fi3rce zrób to tak jak Ci wygodnie i wstaw obok komentarz co to robi żeby nikt nie miał problemu...
Jeżeli nie chcesz użyć ==, a jesteś pewny, że w stringu będzie 1 lub 0 możesz zostawić to tak jak napisałeś.

@ przykład z parseint był o wieele mniej optymalny :P

0
_naf napisał(a):

Nie jestem fanem unikania czegokolwiek w kodzie z powodu "ktoś nie wie i namiesza". Ktoś kto nie zauważy różnicy pomiędzy == i === nie powinien pracować z js.

Nie do końca się zgodzę. Trzeba mieć przede wszystkim na uwadze czytelność kodu i łatwość zrozumienia go przez inną osobę lub nawet ciebie, gdy siądziesz do niego po kilku tygodniach czy miesiącach. Coercion wykorzystywane z głową może dużo rzeczy ułatwić - jasne, sam mechanizm nie jest zły. Problem jest w tym, że nadużycia są złe, side effecty są złe. Pół biedy jeśli masz dobre testy napisane do metod, ale życie pokazuje, że tak nie jest. Testy dla frontendowców to nadal czarna magia, refactoring to wielkie zło dla osób biznesowych, itd. W konsekwencji ktoś może nie zrozumieć twojej intencji bez debugowania kodu, co skutkuje stratą jego czasu. Zarzucisz niekompetencję osobie, która kilkanaście godzin debuguje gówniany kod, bo ktoś użył dajmy na to with w JS i namieszał, nie pisząc do tego pojedynczego testu? Bez jaj, proszę cię. Wielokrotnie zdarzyło mi się, że przeoczyłem coś w kodzie omyłkowo, bo po człowiek po prostu popełnia błędy każdego dnia. Statyczna analiza, czy to podstawowa jshintem czy bardziej złożona gulpem/gruntem (netflix?), strict mode, testy - to pomaga, ale nadal nie zawsze.

Świadomość tego, co dzieje się pod spodem warto mieć, ale nie warto wszystkiego używać tylko dlatego, bo można. Nie piszemy kodu tylko dla siebie, ale z myślą o innych członkach teamu tych obecnych i tych, którzy przejmą kod po twoim odejściu, nie wiedząc nawet czego dotyczy projekt.

0

Nie przechodźmy z jednej skrajności w drugą :) Wykorzystujesz te "złe" elementy tylko jak nie ma sensu ich zastępować.
Czasem programiści chcą tak bardzo uniknąć tych "złych" elementów, że piszą jeszcze gorszy kod w zamian.
Jeżeli wiesz jak coś zastąpić - ok, nie wiesz - napisz komentarz obok takiego fragmentu kodu.

0

Ktoś kto nie zauważy różnicy pomiędzy == i === nie powinien pracować z js.

Świat nie jest idealny, wręcz przeciwnie. Taki ktoś "nie powinien", ale będzie. Wielu takich będzie.

A odnośnie kolejnego posta: akurat unikanie == nie jest ani trudne, ani nie pozbawia Cię niczego szczególnie przydatnego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1