Math.min 与 Math.max
Math.min/max 空参数返回 Infinity/-Infinity,参数会做 ToNumber 转换,不直接接收数组需用展开运算符。
#type / concept
#status / evergreen
#resource / javascript
#resource / ecmascript
[!info] related notes
- 相关概念: ecmascript-type-conversion, typeof
- 对比:
Array.prototype.reduce求最值
Math.min 与 Math.max
一句话定义
Math.min(v1, v2, ...) 返回参数中最小值,Math.max(v1, v2, ...) 返回最大值。参数会经过 ToNumber 转换,空调用返回 Infinity / -Infinity。
签名
Math.min(value1, value2, /* ... */, valueN)
Math.max(value1, value2, /* ... */, valueN)
接收的是参数列表,不是数组。
空参数的默认边界值
Math.min() // Infinity
Math.max() // -Infinity
原因:归约初始值设计。
min要不断取更小值,初始值设成Infinity(任何实数都比它小)max要不断取更大值,初始值设成-Infinity(任何实数都比它大)
参数的 ToNumber 转换
每个参数会先经过 Number() 转换,再参与比较:
Math.min("3") // 3 Number("3") = 3
Math.min(null) // 0 Number(null) = 0
Math.min(undefined) // NaN Number(undefined) = NaN
Math.min([]) // 0 Number([]) = 0
Math.min([1]) // 1 Number([1]) = 1
Math.min([1, 2]) // NaN Number([1,2]) = NaN("1,2" 无法转数字)
Math.min([1, 2, 3]) // NaN Number([1,2,3]) = NaN
[1,2,3] 作为单个参数时的转换过程:
[1, 2, 3].toString() // "1,2,3"
Number("1,2,3") // NaN
不是取数组里的最小值 1,而是整个数组转成 NaN。
数组不能直接传
Math.min([1, 2, 3]) // NaN(数组整体作为第一个参数)
正确写法:用展开运算符把数组拆成参数列表:
Math.min(...[1, 2, 3]) // 1
Math.max(...[1, 2, 3]) // 3
// 等价于
Math.min(1, 2, 3)
常见用法
Math.min(1, 2, 3) // 1
Math.max(1, 2, 3) // 3
Math.min(-5, 0, 10) // -5
Math.max(...array) // 数组最大值
Math.min(...array) // 数组最小值
用 reduce 求数组最值
如果不想用展开运算符(大数组可能超过参数数量限制):
const arr = [3, 7, 2, 9];
arr.reduce((max, cur) => cur > max ? cur : max) // 9
arr.reduce((min, cur) => cur < min ? cur : min) // 2
参数数量限制
展开运算符受引擎的参数数量限制(通常约 65536 或更低)。超大数组用 reduce 更安全。
面试高频延伸
Math.min() // Infinity
Math.max() // -Infinity
Math.min("3") // 3
Math.min(null) // 0
Math.min(undefined) // NaN
Math.min([]) // 0
Math.min([1]) // 1
Math.min([1, 2]) // NaN
Math.min([1, 2, 3]) // NaN
Math.min(...[1, 2, 3]) // 1
本质都在考 ToNumber 规则。