Dlaczego „,,,” == Array (4) w Javascript?


119

Uruchom interpreter / konsolę i spróbuj porównać

> ",,," == Array(4)
True

Czemu? Na początku pomyślałem, że może skoro można by pomyśleć o „,,,” jako tablicy czterech znaków z końcowym wycinkiem „\ 0”, to może być przyczyna, ale

> "..." == Array(4)

Zwraca wartość „False”. Więc dlaczego? Wiem, że w Javascript jest to trochę specyficznego kaczego wpisywania, ale jestem po prostu ciekawy, co podkreśla to zachowanie. Przy okazji, przeczytałem to z doskonałej prezentacji Zeda Shawa .


14
Niewiele języków poza C używa terminacji zerowej w sposób widoczny dla programisty.
Joey,

7
Jeśli mogę zapytać, co doprowadziło do tego odkrycia?
SomeKittens,

1
@SomeKittens Zed Shaw wspomina o tym wyraźnie w filmie, do którego umieściłem link w moim pytaniu (jako krytyka Javascript). Twoje zdrowie!
ZenLikeThat

5
@SomeKittens to również wspomniane w (dość dobrze znany) „wat” talk, pokazując jakieś dziwactwa w Ruby i JavaScript destroyallsoftware.com/talks/wat
Cronco

5
To jeden z wielu dobrych powodów, dla których warto zawsze używać ===zamiast ==.
wprl

Odpowiedzi:


178

Ponieważ operand po prawej stronie jest konwertowany na łańcuch, a reprezentacja ciągu Array(4)to ,,,:

> Array(4).toString()
  ",,,"

Jeśli używasz funkcji konstruktora tablicy i przekażesz liczbę, ustawia ona długość tablicy na tę liczbę. Możesz więc powiedzieć, że masz cztery puste indeksy (takie same jak [,,,]), a domyślną reprezentacją tablic w postaci ciągów jest lista ich elementów oddzielonych przecinkami:

> ['a','b','c'].toString()
  "a,b,c"

Sposób działania porównania opisano w sekcji 11.9.3 specyfikacji . Tam zobaczysz ( x == y):

8. Jeśli Type ( x ) to String lub Number, a Type ( y ) to Object,
zwróć wynik porównania x == ToPrimitive ( y ).

(tablice są obiektami w JavaScript)

a jeśli zastosujesz się do tej ToPrimitivemetody, w końcu przekonasz się, że ona wywołuje toString.


2
Okej, teraz to wszystko ma dla mnie sens. Dzięki.
ZenLikeThat

6
Co z kolei jest spowodowane tym, że tablice określają łańcuchy tak, jakby były używane Array.join(",").
duskwuff

Musisz być cholernie cierpliwy, żeby programować w javascript
mecz


31

Spróbuj użyć ===. Podczas używania ==w JavaScript spróbuje rzutować zmienne, prowadząc w ten sposób do problemów takich jak ten. Konsola rzutuje Array(4)na reprezentację ciągu (tj. Array(4).toString), Którą jest ",,,". Przyczyną występowania przecinków jest to, że .toString()funkcja dodaje je do oddzielnych elementów w tablicy.

Zobacz fragment poniżej:

document.write( Array(4).toString() );


18

Dzieje się tak, ponieważ Array(4)inicjalizuje tablicę 4 pustych wartości, a ==niejawnie konwertuje, więc:

 ",,," == Array(4)

 ",,," == Array(4).toString()

 ",,," == ["", "", "", ""] // note 3 commas for 4 values

 ",,," == ["", "", "", ""].toString()

Są podobne.

==wykonuje niejawne konwersje typów przed porównaniem wartości, co może skutkować nieprzewidywalnymi wynikami. Służy ===do sprawdzania typu i wartości.


5

Porównanie Array z ciągiem wymusza wymuszenie Array na łańcuchu przed wykonaniem porównania. Zmuszenie pustej 4-elementowej tablicy Array do łańcucha daje dokładnie ten ciąg.


4

Na początku myślałem, że to coś z „prototypem”… ale po krótkim śledztwie doszedłem do smutnego wniosku…

Najwyraźniej jest to wewnętrzna i bardziej niejasna rzecz js z niewielką logiką ...

Spróbuj

Array(4)==Array(4)

i żadnego przymusu na typach też ...

Array(4)===Array(4)

a otrzymasz FALSE

wiesz o tym null==null, null===nulla nawet undefined==undefinedi undefined===undefinedzwraca PRAWDA ... więc ... to trochę niejasne ...

Array(4)==[,,,] powinno być również prawdziwe


ZEE, Array (4) == [,,,] nie będzie prawdziwe. Jeśli porównamy obiekt z prymitywem, to obiekt zostanie przekształcony w prymityw. To jest powód, dla którego wywołuje toString ().
devsathish

tablica (x) powinna być adresem konstruktora ... w każdym razie w systemie (nie przejmuj się jakim systemem), <identity_X> === <identity_X> zawsze powinno być prawdziwe!
ZEE
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.