es6 - ¿Por qué Array.filter(Número) filtra cero en JavaScript?
map javascript (6)
Comportamiento esperado
Este comportamiento no es exclusivo de usar Número como la función de filtro. Una función de filtro que simplemente devuelve el valor 0
también lo eliminaría de la lista.
var a = [-1, 0, 1, 2, 3, 4, Number(0), '''', ''test''].filter(v => v)
console.log(a); // [-1, 1, 2, 3, 4, "test"]
Esto se debe a que Number
no es específicamente una función de filtro, es principalmente una función de conversión de tipos (y un constructor de clases, pero no muy útil). Entonces, cuando un número (como 0
) se pasa a Number
, simplemente devuelve ese número.
Array.prototype.filter() elimina los valores que son falsy . En JavaScript, las siguientes son falsas y, por lo tanto, eliminadas por filter
.
false
null
undefined
0
NaN
''''
""
``
(Por razones complicadas de compatibilidad con versiones anteriores, MDN entra , document.all
también es falsa en muchos navegadores a pesar de ser un objeto, pero eso es una nota al margen)
Estoy tratando de filtrar todos los elementos no numéricos de una matriz. Podemos ver la salida deseada cuando usamos typeof. Pero con Number, filtra a cero.
Aquí está el ejemplo (probado en la consola de Chrome):
[-1, 0, 1, 2, 3, 4, Number(0), '''', ''test''].filter(Number)
// Which output with zero filtered out:
[-1, 1, 2, 3, 4] // 0 is filtered
Si usamos typeof, no filtra cero, como se esperaba.
// code
[-1, 0, 1, 2, 3, 4, Number(0), '''', ''test''].filter(n => typeof n === ''number'')
// output
[-1, 0, 1, 2, 3, 4, 0]
Mi pregunta:
¿Cuál es la diferencia entre los enfoques de ''Número'' y ''Tipo de''?
El número filtra cero, pero el ''Número'' en sí contiene literalmente cero, y esto me confunde.
Cuando está usando el número en el filtro, en realidad está pasando cada elemento del constructor de Arrays al número y en caso de cadena o 0, el Número devolverá NaN o 0 y ambos son falsos, por lo que el filtro los está filtrando
mientras que cuando usas typeof, 0 tiene el tipo "número", por lo que está devolviendo verdadero y el método de filtro no lo filtra
El cero es un valor falso. El typeof siempre está devolviendo un valor booleano. Cuando se devuelve el número 0, vuelve a la prueba y, por lo tanto, vuelve como falso, por lo que el número cero se filtra.
Para evitar que se falsy un cero falsy , puede usar otra devolución de llamada para obtener solo valores numéricos: Number.isFinite
console.log([-1, 0, 1, 2, 3, 4, Number(0), '''', ''test''].filter(Number.isFinite))
Porque 0
es uno de los muchos valores falsy
en javascript
Todas estas condiciones serán enviadas a los bloques else
:
if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('''')
if ("")
if (``)
De la documentación Array.prototype.filter()
:
filter()
llama a una función decallback
proporcionada una vez para cada elemento en una matriz, y construye una nueva matriz de todos los valores para los que la devolución de llamada devuelve un valor que obliga a verdadero
En su caso, la función de devolución de llamada es el Number
. Entonces tu código es equivalente a:
[-1, 0, 1, 2, 3, 4, Number(0), '''', ''test''].filter(a => Number(a))
// Number(0) -> 0
// Number(Number(0)) -> 0
// Number('''') -> 0
// Number(''test'') -> NaN
// When filter function picks *truthy* values, all the above are ignored
// So, it returns [-1, 1, 2, 3, 4]
Se debe a que 0 es un valor falso que devuelve falso, y todo lo que devuelve falso a la función de filtro se filtra de la nueva matriz.