Por que ",,," == Matriz (4) em Javascript?

119

Inicialize seu intérprete / console e tente a comparação

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

Por quê? No começo, pensei que talvez você pudesse pensar em ",,," como uma matriz de quatro caracteres com uma fatia de terminação '\ 0', talvez por isso, mas

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

Retorna "Falso". Então por que? Eu sei que é um pouco idiossincrático de digitação de pato em Javascript, mas apenas curioso o que sublinha esse comportamento. Recolheu isso da excelente apresentação de Zed Shaw aqui .

ZenLikeThat
fonte
14
Poucas linguagens além de C usam terminação zero de uma maneira visível para o programador.
Joey
7
Se posso perguntar, o que levou a essa descoberta?
precisa saber é o seguinte
1
O @SomeKittens Zed Shaw menciona isso explicitamente no vídeo ao qual vinculei minha pergunta (como uma crítica ao Javascript). Felicidades!
ZenLikeThat
5
@SomeKittens Isso também é mencionado no (muito bem conhecido) talk "wat", mostrando algumas peculiaridades em Ruby e JavaScript destroyallsoftware.com/talks/wat
Cronco
5
Essa é uma das muitas boas razões para usar sempre em ===vez de ==.
wprl

Respostas:

178

Como o operando do lado direito é convertido em uma string e a representação da string Array(4)é ,,,:

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

Se você usar a função construtora da matriz e passar um número, ela definirá o comprimento da matriz para esse número. Portanto, você pode dizer que possui quatro índices vazios (o mesmo que [,,,]) e a representação de string padrão de matrizes é uma lista separada por vírgula de seus elementos:

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

Como a comparação funciona é descrito na seção 11.9.3 da especificação . Lá você verá ( x == y):

8. Se Type ( x ) for String ou Number e Type ( y ) for Object,
retorne o resultado da comparação x == ToPrimitive ( y ).

(matrizes são objetos em JavaScript)

e se você seguir o ToPrimitivemétodo, acabará descobrindo que ele chama toString.

Felix Kling
fonte
2
Ok, agora tudo isso faz sentido para mim. Obrigado.
usar o seguinte código
6
O que, por sua vez, ocorre porque as matrizes se estratificam como se estivessem usando Array.join(",").
duskwuff -inactive-
Você tem que ser sangrenta paciente a programar em javascript
matcheek
31

Internamente está indo

",,," == Array(4).toString()
Jason Kulatunga
fonte
31

Tente usar ===. Ao usar ==em Javascript, ele tentará converter as variáveis, levando a problemas como este. O console está transmitindo Array(4)para a representação de sequência (ou seja Array(4).toString), que é ",,,". O motivo das vírgulas existirem é que a .toString()função as adiciona aos itens separados em uma matriz.

Veja o trecho abaixo:

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

SomeKittens
fonte
18

Isso ocorre porque Array(4)inicializa uma matriz de 4 valores vazios, um ==converte implicitamente, portanto:

 ",,," == Array(4)

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

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

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

São todos semelhantes.

==faz conversões implícitas de tipo antes de comparar os valores, o que pode resultar em resultados imprevisíveis. Use ===para verificar o tipo e o valor.

Keith
fonte
5

A comparação de uma matriz com uma cadeia de caracteres força a matriz a uma cadeia de caracteres antes de fazer a comparação. Coagir uma matriz de 4 elementos vazia a uma sequência produz a sequência exata.

Russell Borogove
fonte
4

Eu primeiro pensei que era algo com o "protótipo" ... mas depois de um pouco de investigação cheguei a uma conclusão triste ...

Aparentemente, é uma coisa js interna e mais obscura, com pouca lógica ...

Apenas tente

Array(4)==Array(4)

e sem coerção sobre os tipos também ...

Array(4)===Array(4)

e você terá FALSE

você sabe disso null==null, null===nulle até undefined==undefinede undefined===undefinedretorna VERDADEIRO ... então ... é um pouco obscuro ...

Array(4)==[,,,] deve ser verdade também

ZEE
fonte
ZEE, Matriz (4) == [,,,] não será verdadeira. Se compararmos objeto com primitivo, o objeto será convertido em primitivo. Esse é o motivo pelo qual chama toString ().
Devsathish
array (x) deve ser o endereço do construtor ... de qualquer maneira, em um sistema (não se preocupe com o tipo de sistema), <identity_X> === <identity_X> sempre deve ser verdadeiro!
ZEE