你知道 +0 与 -0 的区别吗?
JavaScript 的数值 Number 用 64 位的浮点数表示,首位是符号位,然后是 52 位的整数位和 11 位的小数位。如果符号位为 1,其他各位均为 0,那么这个数值会被表示成 -0
。
所以 JavaScript 的 “0” 值有两个,+0
和 -0
。
const num = -0
console.log(num) // -0
我们可以用二进制位构造出 -0
来:
// 首先创建一个8位的ArrayBuffer
const buffer = new ArrayBuffer(8)
// 创建DataView对象操作buffer
const dataView = new DataView(buffer)
// 将第1个字节设置为0x80,即最高位为1
dataView.setUint8(0, 0x80)
// 将buffer内容当做Float64类型返回
console.log(dataView.getFloat64(0)) // -0
在一般的运算中,我们也有可能产生 -0
值,比如运算时将 -Infinity
作为分母,负数除法超过最小可表示数等:
console.log(1 / -Infinity) // -0
console.log(-1 / Infinity) // -0
console.log(-Number.MIN_VALUE / 2) // -0
console.log(-1e-1000) // -0
一般情况下 -0
视同于 0,运算并没有什么问题:
console.log(-0 === 0) // true
const num = -0
if (!num) {
// !num 为 true
// do sth.
}
除非在分母中有 -0
存在,恰好又要判断符号的时候,可能会出问题:
const num = -0
console.log(1 / num > 0) // false
console.log(Math.sign(1 / num)) // -1
所以如果你知道分母中可能出现 0 的时候,就要小心 -0
。
-0
也有好处,我们可以利用 -0
来表示状态,比如我们在寻路的时候,把地图的障碍物用 1 表示,空地用 0 表示,那么我们就可以把未搜索过的用 -1 和 -0
表示,这样也挺方便的。
另外比如我们要存 mousemove 的坐标位置,那么当鼠标移动出检测范围的时候,可以把 mousePosition 设为 -0
来表示当前鼠标不在范围内。
如果要使用 -0
,我们就得区分它与 0。
用 num === -0
是不行的,因为 0 === -0
也会返回 true
。
用 Math.sign
也是不行的,Math.sign
一共会返回 4 种值:
console.log(Math.sign(0)) // 0
console.log(Math.sign(-0)) // -0
console.log(Math.sign(0.01)) // 1
console.log(Math.sign(-0.01)) // -1
实际上在 ES2015 中提供了 Object.is
方法,可以判断 -0
.
👉🏻 【冷知识】Object.is(value1, value2)
比较两个值是否相同。它与 ===
的区别是,Object.is(-0, 0)
返回 false
,Object.is(NaN, NaN)
返回 true
。
如果在早期的 JavaScript 版本中,我们也可以利用 1/-0
为 -Infinity
的特点来判断:
function isNegativeZero(num) {
return num === 0 && 1 / num < 0
}
或者我们可以写一个 Object.is
的 polyfill:
if (!Object.is) {
Object.is = function (x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y
}
else {
// Step 6.a: NaN == NaN
return x !== x && y !== y
}
}
}
补充,所有位运算都会把 -0
转为 0。因为位运算首先会转成 int32,而 int32 是没有 -0
的。另外 bigint 里也是没有 -0
的,所以 Object.is(0n, -0n)
返回 true
。
再补充一个序列化有关的坑:JSON.parse("-0")
返回 -0
然而 JSON.stringify(-0)
返回 "0"
,所以是不对称的。
文章作者 akira-cn,原文地址 你知道 +0 与 -0 的区别吗?,转载请注明出处。