SameValueZero 是 JavaScript 中的一种相等性比较算法,主要用于某些内置操作(如 Array.includes()、Set 和 Map),与严格相等运算符 === 类似,但在处理 NaN 和 正负零时有特殊规则。
算法规则
基本比较流程
- 类型检查:如果两个值类型不同,直接返回 false
- 非数值类型:按
===规则比较(类型相同且值相同则为 true) - 数值类型:特殊处理以下情况:
数值类型特殊规则(Number 类型)
| 情况 | SameValueZero 返回值 |
|---|---|
| x 和 y 都是 NaN | true |
| x 是 +0 且 y 是 -0 | true |
| x 是 -0 且 y 是 +0 | true |
| x 和 y 数值相等(非 NaN、非零) | true |
| 其他情况 | false |
注:这与 === 的唯一区别是:=== 认为 NaN 不等于自身,且 +0 等于 -0;而 SameValueZero 认为 NaN 等于自身,且同样认为 +0 等于 -0(与 === 在零的处理上一致)。
与其他相等算法的对比
| 比较算法 | 实现方式 | +0 == -0 | NaN == NaN | 使用场景 |
|---|---|---|---|---|
| SameValueZero | 内置算法(无直接 API) | true | true | Array.includes()、Set、Map 等 |
| === (严格相等) | JavaScript 运算符 | true | false | 大多数需要类型严格比较的场景 |
| Object.is() | JavaScript 方法 | false | true | 需要精确区分 +0 和 -0 的场景 |
| == (宽松相等) | JavaScript 运算符 | true | false | 类型自动转换的宽松比较 |
实现方式
虽然 SameValueZero 没有直接作为 JavaScript API 公开,但可以自定义实现:
function sameValueZero(x, y) {
if (typeof x === "number" && typeof y === "number") {
// 处理 NaN 和正负零
return x === y || (x !== x && y !== y); // x !== x 检测 NaN
}
// 其他类型按 === 比较
return x === y;
}
应用场景
SameValueZero 算法主要用于以下内置操作:
Array.prototype.includes(searchElement):判断数组是否包含特定元素时使用
const arr = [0, NaN];
arr.includes(-0); // true
arr.includes(NaN); // true
Set数据结构:在添加和查询元素时用于去重和相等性检查
const set = new Set([0, NaN]);
set.has(-0); // true
set.has(NaN); // true
Map数据结构:用于键的相等性比较
为什么选择 SameValueZero?
在搜索和集合操作中,SameValueZero 提供了更符合直觉的行为:
- NaN 被视为自等:在数据搜索中,我们通常希望所有 NaN 值被视为相同(例如,查找数组中的无效数字)
- 不区分正负零:在大多数应用场景中,0 和 -0 的差异并不重要,将它们视为相等更合理
总结
SameValueZero 是 JavaScript 中一种特殊的相等性比较算法,它与 === 基本相同,但在处理 NaN 和 正负零时有特殊规则。它主要用于 Array.includes()、Set、Map 等内置操作,为这些数据结构提供了更符合直觉的相等性判断。