为什么Array.filter(Number)在JavaScript中过滤掉零?

时间:2018-12-25 06:52:07

标签: javascript numbers typeof

我正在尝试从数组中过滤掉所有非数字元素。使用typeof时,我们可以看到所需的输出。但是使用Number时,它会将零过滤掉。

以下是示例(已在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

如果我们使用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. “数字”方法和“类型”方法有什么区别?

  2. 数字过滤为零,但是“数字”本身实际上包含零,这使我感到困惑。

9 个答案:

答案 0 :(得分:34)

因为0是javascript中许多falsy值之一

所有这些条件都将发送到else块:

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

摘自Array.prototype.filter()文档:

  

filter()为数组中的每个元素调用一次提供的callback函数,并为所有值构造一个新数组,为此,回调返回一个强制为true的

在您的情况下,回调函数为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

filter函数选择truthy个值(或强制转换为true的值)时,返回0NaN的项目将被忽略。因此,它将返回[-1, 1, 2, 3, 4]

答案 1 :(得分:12)

为防止过滤falsy零,您可以使用另一个回调仅获取数值:Number.isFinite

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

答案 2 :(得分:5)

预期行为

使用数字作为过滤器功能并非唯一。简单返回0值的过滤器功能也会将其从列表中删除。

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

这是因为Number并不是特定的过滤器函数,它主要是类型转换函数(和类构造函数,但不是一个非常有用的函数)。因此,当将数字(例如0)传递给Number时,它只会返回该数字。

Array.prototype.filter删除值为falsy的值。在JavaScript中,以下内容是虚假的,因此被filter删除。

false
null
undefined
0
NaN
''
""
``

(出于复杂的向后兼容性原因,MDN goes intodocument.all在许多浏览器中尽管是对象也很虚假,但这只是一个旁注)

答案 3 :(得分:4)

零是一个假值。 typeof始终返回布尔值。返回数字0时,它将返回测试,因此返回为false,因此将数字0过滤掉。

答案 4 :(得分:3)

这是因为0是一个伪造的值,它返回false,并且将向filter函数返回false的所有内容都从新数组中过滤掉。

文档

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

答案 5 :(得分:3)

在过滤器中使用Number时,实际上是将Array的每个项目传递给Number构造函数,如果是字符串或0,则Number将返回NaN或0,并且两者均为假,因此filter会将它们都过滤掉

而当您使用typeof时,则0为“数字”类型,因此它返回true,并且filter方法不会将其过滤掉

答案 6 :(得分:2)

为防止过滤falsy零,您可以使用另一个回调仅获取数值:Number.isFinite

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

答案 7 :(得分:0)

此行为的原因是0, null, undefined, NaN在JavaScript中等于false,因此,在第一种情况下:

[-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(Number);

当将Number用作过滤器中的参数之一时,它将返回数字本身。因此,当传递0时,它将返回0,而javascript将其理解为false。因此,它返回

[-1, 1, 2, 3, 4]

为了安全起见,建议使用Number.isFinite而不是Number

[-1, 0, 1, 2, 3, 4, Number(0), '', 'test'].filter(Number.isFinite);

给出与

相同的结果
[-1,0,1,2,3,4, Number(0), '','test'].filter(n=> typeof n === 'number');

会给。

答案 8 :(得分:0)

这是另一个示例,显示了如何从数字数组中删除多个索引并处理0:

const array = [0,1,2,3,4,5,6,7,8,9]
console.log('init', array)

const indicesToDel = [2, 3, 5, 9]
console.log('indices to del', indicesToDel)

let result = array.filter( (item, index) => !indicesToDel.includes(index) ? Number.isFinite(item) : false )
console.log('result', result)