¿Por qué ",,," == Array (4) en Javascript?

119

Inicie su intérprete / consola y pruebe la comparación

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

¿Por qué? Al principio pensé que tal vez, dado que podrías pensar en ",,," como una matriz de cuatro caracteres con un segmento de terminación '\ 0', esa podría ser la razón, pero

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

Devuelve "Falso". ¿Entonces por qué? Sé que es un poco idiosincrásico de tipeo de pato en Javascript, pero tengo curiosidad por saber qué subraya este comportamiento. Obtuve esto de la excelente presentación de Zed Shaw aquí por cierto .

ZenLikeThat
fuente
14
Pocos lenguajes, aparte de C, usan terminación cero de una manera visible para el programador.
Joey
7
Si puedo preguntar, ¿qué condujo a este descubrimiento?
SomeKittens
1
@SomeKittens Zed Shaw menciona esto explícitamente en el video al que vinculé en mi pregunta (como una crítica a Javascript). ¡Salud!
ZenLikeThat
5
@SomeKittens Esto también se menciona en la (bastante conocida) charla "wat", que muestra algunas peculiaridades en Ruby y JavaScript destroyallsoftware.com/talks/wat
Cronco
5
Esta es una de las muchas buenas razones para usar siempre en ===lugar de ==.
wprl

Respuestas:

178

Porque el operando de la derecha se convierte en una cadena y la representación de la cadena Array(4)es ,,,:

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

Si usa la función de constructor de matriz y pasa un número, establece la longitud de la matriz en ese número. Por lo tanto, puede decir que tiene cuatro índices vacíos (igual que [,,,]) y la representación de cadena predeterminada de las matrices es una lista separada por comas de sus elementos:

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

El funcionamiento de la comparación se describe en la sección 11.9.3 de la especificación . Allí verá ( x == y):

8. Si Tipo ( x ) es Cadena o Número y Tipo ( y ) es Objeto,
devuelva el resultado de la comparación x == ToPrimitive ( y ).

(las matrices son objetos en JavaScript)

y si sigue el ToPrimitivemétodo, eventualmente encontrará que llama toString.

Felix Kling
fuente
2
Bien, ahora todo esto tiene sentido para mí. Gracias.
ZenLikeThat
6
Lo cual, a su vez, se debe a que las matrices se encadenan como si estuvieran usando Array.join(",").
anochecer-inactivo-
Tienes que ser paciente con sangre a programar en Javascript
matcheek
31

Internamente va

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

Intente usar ===. Cuando se usa ==en Javascript, intentará convertir las variables, lo que generará problemas como este. La consola está transmitiendo Array(4)a la representación de cadena (es decir Array(4).toString), que es ",,,". La razón por la que las comas están ahí es que la .toString()función las agrega a elementos separados en una matriz.

Vea el fragmento a continuación:

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

Algunos gatitos
fuente
18

Esto se debe a que Array(4)inicializa una matriz de 4 valores vacíos, y ==convierte implícitamente, por lo que:

 ",,," == Array(4)

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

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

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

Son todos similares.

==realiza conversiones de tipo implícitas antes de comparar los valores, lo que puede dar lugar a resultados impredecibles. Use ===para verificar el tipo y el valor.

Keith
fuente
5

La comparación de una matriz con una cadena convierte la matriz en una cadena antes de realizar la comparación. Forzar una matriz vacía de 4 elementos a una cadena produce esa cadena exacta.

Russell Borogove
fuente
4

Primero pensé que era algo con el "prototipo" ... pero después de una pequeña investigación llegué a una triste conclusión ...

Aparentemente es una cosa js interna y más oscura sin mucha lógica ...

Sólo inténtalo

Array(4)==Array(4)

y sin coerción sobre tipos también ...

Array(4)===Array(4)

y obtendrás FALSO

lo sabes null==null, null===nulle incluso undefined==undefinedy undefined===undefineddevuelve VERDADERO ... así que ... es un poco oscuro ...

Array(4)==[,,,] debería ser verdad también

ZEE
fuente
ZEE, Array (4) == [,,,] no será cierto. Si comparamos objeto con primitivo, entonces el objeto se convertirá en primitivo. Esa es la razón por la que llama a toString ().
devsathish
array (x) debería ser la dirección del constructor ... de todos modos, en un sistema (no te molestes en qué tipo de sistema), <identity_X> === <identity_X> ¡siempre debería ser cierto!
ZEE