web-dev-qa-db-fra.com

Pourquoi Array.filter (Number) filtre-t-il en JavaScript?

J'essaie de filtrer tous les éléments non numériques d'un tableau. Nous pouvons voir la sortie souhaitée lorsque vous utilisez typeof. Mais avec Number, il filtre à zéro.

Voici l'exemple (testé dans Chrome Console):

[-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 nous utilisons typeof, il ne filtre pas le zéro, comme prévu.

// code
[-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(n => typeof n === 'number')
// output
[-1, 0, 1, 2, 3, 4, 0]

Ma question:

  1. Quelle est la différence entre les approches "Nombre" et "Typeof"?

  2. Nombre filtres zéro, mais "nombre" lui-même contient littéralement zéro, et cela me perturbe.

41
imckl

Parce que 0 Est l’un des nombreux falsy valeurs en javascript

Toutes ces conditions seront envoyées à else blocs:

if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (``)

À partir de la documentation Array.prototype.filter() :

filter() appelle une fonction callback fournie une fois pour chaque élément d'un tableau et construit un nouveau tableau de toutes les valeurs pour lesquelles callback renvoie une valeur qui coercite à true

Dans votre cas, la fonction de rappel est le Number. Donc, votre code est équivalent à:

[-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

Lorsque filter fonction sélectionne vérité valeurs (ou des valeurs coercitives à true), les éléments renvoyant 0 Et NaN sont ignoré. Donc, il retourne [-1, 1, 2, 3, 4]

36
adiga

Pour empêcher le filtrage de falsy zéro, vous pouvez utiliser un autre rappel pour obtenir uniquement des valeurs numériques: Number.isFinite

console.log([-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(Number.isFinite))
12
Nina Scholz

Comportement attendu

Ce comportement n'est pas propre à l'utilisation de Number en tant que fonction de filtre. Une fonction de filtrage aussi simple que retourne le 0 value le supprimerait également de la liste.

var a = [-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(v => v)
console.log(a); // [-1, 1, 2, 3, 4, "test"]

Ceci est dû au fait que Number n'est pas spécifiquement une fonction de filtrage, mais une fonction de transtypage (et un constructeur de classe, mais pas très utile). Alors, quand un nombre (comme 0) est passé à Number, il ne fait que renvoyer ce nombre.

Array.prototype.filter supprime les valeurs qui sont fausseté . En JavaScript, les éléments suivants sont faussés et donc supprimés par filter.

false
null
undefined
0
NaN
''
""
``

(Pour des raisons complexes de compatibilité descendante MDN va dans , document.all est aussi une fausseté dans de nombreux navigateurs alors qu’il s’agit d’un objet, mais c’est une note secondaire.)

5
Alexander O'Mara

Zero est une valeur Falsey. Le typeof renvoie toujours une valeur booléenne. Lorsque le nombre 0 est renvoyé, il retourne au test et revient donc à faux. Le nombre zéro est filtré.

4
bronkula

C'est parce que 0 est une valeur falsy qui renvoie false et que tout ce qui renvoie false à la fonction de filtrage est filtré du nouveau tableau.

Documentation

https://developer.mozilla.org/en-US/docs/Glossary/Falsy

3
AnonymousSB

Lorsque vous utilisez Number dans le filtre, en réalité, il passe chaque élément du constructeur Array to Number et, en cas de chaîne ou 0, Number retournera NaN ou 0 et les deux sont faux, le filtre les éliminant.

alors que lorsque vous utilisez typeof, 0 a le type "number", donc il renvoie true et la méthode de filtrage ne le filtre pas

3
Abhay Sehgal