Почему Array.filter(Number) фильтрует обнуление в JavaScript?
Я пытаюсь отфильтровать все нечисловые элементы из массива. Мы можем видеть желаемый результат при использовании typeof. Но с Number он фильтрует ноль.
Вот пример (проверено в 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
Если мы используем typeof, он не фильтрует ноль, что и ожидалось.
// code
[-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(n => typeof n === 'number')
// output
[-1, 0, 1, 2, 3, 4, 0]
Мой вопрос:
-
В чем разница между подходами "число" и "типоф"?
-
Число фильтрует ноль, но само "Число" буквально содержит ноль, и это меня смущает.
Ответы
Ответ 1
Потому что 0
является одним из многих falsy
значений в JavaScript
Все эти условия будут отправлены в else
блоки:
if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if ('')
Из документации Array.prototype.filter()
:
filter()
вызывает предоставленную callback
один раз для каждого элемента в массиве и создает новый массив всех значений, для которых обратный вызов возвращает значение, которое приводит к истине
В вашем случае функцией обратного вызова является Number
. Итак, ваш код эквивалентен:
[-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]
Ответ 2
Чтобы не допустить фильтрации ложного нуля, вы можете использовать другой обратный вызов для получения только числовых значений: Number.isFinite
console.log([-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(Number.isFinite))
Ответ 3
Ожидаемое поведение
Это поведение не уникально для использования Number в качестве функции фильтра. Функция фильтра, которая просто возвращает значение 0
, также удалит его из списка.
var a = [-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(v => v)
console.log(a); // [-1, 1, 2, 3, 4, "test"]
Ответ 4
Ноль - это фальшивое значение. Typeof всегда возвращает логическое значение. Когда возвращается число 0, оно возвращается к тесту и, следовательно, возвращается как ложное, поэтому нулевое число отфильтровывается.
Ответ 5
Это потому, что 0 - ложное значение, которое возвращает false, а все, что возвращает false для функции фильтра, отфильтровывается из нового массива.
Документация
https://developer.mozilla.org/en-US/docs/Glossary/Falsy
Ответ 6
Когда вы используете Number в фильтре, фактически он передает каждый элемент массива конструктору Number, а в случае строки или 0 Number возвращает NaN или 0, и оба они имеют значение false, поэтому фильтр отфильтровывает оба из них.
тогда как когда вы используете typeof, тогда 0 имеет тип "число", поэтому он возвращает true, а метод filter не фильтрует его