比较运算的详细说明


  • NaN 之外,使用抽象的相等性比较==)来比较原始值。如果双方均为 NaN,则视为相同。
  • 对象的类型标签应该相同。
  • 只考虑可枚举的自身属性
  • 始终比较 Error 的名称和消息,即使这些不是可枚举的属性。
  • 对象封装器作为对象和解封装后的值都进行比较。
  • Object 属性的比较是无序的。
  • Map 键名与 Set 子项的比较是无序的。
  • 当两边的值不相同或遇到循环引用时,递归停止。
  • 不测试对象的 [[Prototype]]
  • 可枚举的自身 Symbol 属性也会比较。
  • WeakMapWeakSet 的比较不依赖于它们的值。

以下示例不会抛出 AssertionError,因为抽象的相等性比较==)会将原始类型视为相等。

// 不会抛出 AssertionError。
assert.deepEqual('+00000000', false);

“深度”相等意味着还会比较子对象的可枚举“自有”属性:

const assert = require('assert');

const obj1 = {
  a: {
    b: 1
  }
};
const obj2 = {
  a: {
    b: 2
  }
};
const obj3 = {
  a: {
    b: 1
  }
};
const obj4 = Object.create(obj1);

assert.deepEqual(obj1, obj1);
// OK

// b 的值不同:
assert.deepEqual(obj1, obj2);
// 抛出 AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }

assert.deepEqual(obj1, obj3);
// OK

// 原型会被忽略:
assert.deepEqual(obj1, obj4);
// 抛出 AssertionError: { a: { b: 1 } } deepEqual {}

如果值不相等,则抛出 AssertionError,并将 message 属性设置为等于 message 参数的值。 如果未定义 message 参数,则会分配默认错误消息。 如果 message 参数是 Error 的实例,那么它将被抛出而不是 AssertionError

  • Primitive values are compared with the Abstract Equality Comparison ( == ) with the exception of NaN. It is treated as being identical in case both sides are NaN.
  • Type tags of objects should be the same.
  • Only enumerable "own" properties are considered.
  • Error names and messages are always compared, even if these are not enumerable properties.
  • Object wrappers are compared both as objects and unwrapped values.
  • Object properties are compared unordered.
  • Map keys and Set items are compared unordered.
  • Recursion stops when both sides differ or both sides encounter a circular reference.
  • Implementation does not test the [[Prototype]] of objects.
  • Symbol properties are not compared.
  • WeakMap and WeakSet comparison does not rely on their values.

The following example does not throw an AssertionError because the primitives are considered equal by the Abstract Equality Comparison ( == ).

// WARNING: This does not throw an AssertionError!
assert.deepEqual('+00000000', false);

"Deep" equality means that the enumerable "own" properties of child objects are evaluated also:

const assert = require('assert');

const obj1 = {
  a: {
    b: 1
  }
};
const obj2 = {
  a: {
    b: 2
  }
};
const obj3 = {
  a: {
    b: 1
  }
};
const obj4 = Object.create(obj1);

assert.deepEqual(obj1, obj1);
// OK

// Values of b are different:
assert.deepEqual(obj1, obj2);
// AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }

assert.deepEqual(obj1, obj3);
// OK

// Prototypes are ignored:
assert.deepEqual(obj1, obj4);
// AssertionError: { a: { b: 1 } } deepEqual {}

If the values are not equal, an AssertionError is thrown with a message property set equal to the value of the message parameter. If the message parameter is undefined, a default error message is assigned. If the message parameter is an instance of an Error then it will be thrown instead of the AssertionError.