js 中四种相等

在ES2015中有四种相等算法

ecma规范定义算法规则
7.2.10 SameValue
7.2.11 SameValueZero
7.2.12 SameValueNonNumber
即术语同值同值零同值非零

  • 抽象相等 ==
  • 严格相等 ===,用于
    • Array.prototype.indexOf
    • Array.prototype.lastIndexOf
  • 同值零(SameValueZero),用于
    • Map
    • Set
    • String.prototype.includes
    • ArrayBuffer构造函数
    • TypedArray构造函数
  • 同值(SameValue),用于
    • Object.js()

定义

ECMA中SameValue比较规则

  • 类型不一样,返回false
  • 类型为number
    • 都为NaN,返回true
    • x为+0,y为-0时,返回false
  • 类型不是number时,return SameValueNonNumber()
    1
    2
    3
    4
    5
    NaN === NaN // false
    Object.is(NaN, NaN) // true

    -0 === +0 // true
    Object.is(-0, +0) // false

ECMA中SameValueZero比较规则

  • 类型不一样,返回false
  • 类型为number
    • 都为NaN,返回true
    • x为+0,y为-0时,返回true
  • 类型不是number时,return SameValueNonNumber()
    1
    2
    3
    4
    5
    6
    7
    8
    const foo = new Map()
    foo.set(0, '0') // Map(1) {0 => "0"}
    foo.set('0', 'zero') // Map(2) {0 => "0", "0" => "zero"}
    foo.get(0) // 0
    foo.get('0') // zero
    var arr = [1, 2, NaN];
    arr.indexOf(NaN); // -1
    arr.includes(NaN); // true

SameValue与SameValueZero的差别在于数值类型时+0-0,保证 +0-0 不再相同

ECMA中SameValueNonNumber比较规则

  • Undefined,返回true
  • Null,返回true
  • String,则比较这2个字符串的码点
  • Object,则比较是否指向同一个堆地址

JavaScript提供三种不同的值比较操作:

  • ==
  • ===
  • Object.is

Object.is的行为方式与===相同,但是对于NaN和-0和+0进行特殊处理

1
2
3
4
5
NaN === NaN // false
Object.is(NaN, NaN) // true

+0 === -0 // true
Object.is(+0, -0) // false

可以看到Object.is采用的SameValue算法,而全等可以看作是SameValueZero排除NaN的情况,因为全等操作符认为 NaN 与其他任何值都不全等,包括它自己。