为什么Math.min([])的结果是0?

35
为什么 Math.min([]) 的值为 0
我原本期望它会返回 NaN,因为MDN的Math.min手册中指出:“如果其中至少有一个参数无法转换为数字,则返回 NaN。”
所以我认为问题的重点是为什么 [] 被转化为 0?特别是考虑到 [] 是真值(即!![] === true)和 Math.min(true) === 1。 我对此的思考是否正确?
在Node v7.0.0上测试。

3
一个空数组可以转换成一个数字,即零。 - I wrestled a bear once.
2
因为规范是这样规定的。 - zzzzBov
5
我认为这是因为[].toString()得到的是"",规范规定将""转换成数字会得到0 - Andrew Whitaker
4
这样的东西有什么用处?在JavaScript中隐式和不直观的转换是所有问题的根源。是的,由于向后兼容性,它将永远存在。 - freakish
2
@zzzzBov编程语言的存在是为了让程序员的生活更加轻松。汇编语言就像一把螺丝刀,但我向您保证使用这个工具并不好玩。只有在必要的时候才会使用它。对于JavaScript来说也是如此,你会使用它是因为你必须使用它。您说这些转换非常有用。首先,我不知道这与函数式编程有什么关系。其次,我坚信“明确比含糊好”。我真的很想看到使用这种隐式转换的实际代码,并且易于维护,理解和扩展。 - freakish
显示剩余7条评论
2个回答

36

为什么Math.min([])的结果是0

因为规范是这样规定的:

Math.min将每个参数转换为数字,使用...

ToNumber将对象转换为数字,使用...

ToPrimitive将对象转换为基本值,使用...

[[Default Value]]内部方法根据提示参数将对象转换为基元。

所有对象的默认提示都是字符串。这意味着数组被转换为字符串,对于[]""

ToNumber"" 转换为 0,根据 文档中记录的算法

Math.min 然后使用其算法获取唯一参数并返回它。


2
啊...所以只有长度为0或1的数组才会强制转换,而像Math.min([1,42])这样的东西将导致NaN - jtpeterson

16

这是由于[]被强制转换为0所导致的。

您可以通过以下调用查看:

(new Number([])).valueOf(); // 0
因此,调用Math.min([])与调用Math.min(0)相同,都会得到0
我认为new Number([])[]视为0的原因是:
  1. Number(value)构造函数的规范使用ToNumber函数。
  2. ToNumber(value)函数的规范说明对于object类型(包括数组),应使用ToPrimitive方法。
  3. 数组的原始值等于将数组连接后的字符串,例如[]变成了""[0]变成了"0"[0, 1]变成了"0,1"
  4. 因此,数值构造函数将[]转换为"",然后解析为0
上述行为是一个数组含有一个或两个数字时可以传递给Math.min(...)的原因,但含有更多数字时不行的原因:
  • Math.min([])等同于Math.min("")Math.min(0)
  • Math.min([1])等同于Math.min("1")Math.min(1)
  • Math.min([1, 2])等同于Math.min("1,2"),无法转换为数字。

3
原问题已经意识到了这一点:"所以我想更确切的问题是为什么[]会被强制转换为0"。我认为提问者想知道为什么会发生这种强制转换。 - Andrew Whitaker
1
谢谢。长度为0或1的数组将被强制转换为数字。想想看。这里有一个链接,底部有一个有用的表格,列出了更多的奇怪现象:http://www.w3schools.com/js/js_type_conversion.asp - jtpeterson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接