数组是 JavaScript 中的对象,所以 三等号运算符 === 只返回 true 如果数组是相同的引用。

const a = [1, 2, 3];
const b = [1, 2, 3];

a === a; // true
a === b; // false

如何比较两个数组是否相等? 相等是一个棘手的主题:JavaScript 规范定义了 4 种不同的方法来检查两个值是否 相等,并且没有考虑对象之间的深度相等。

在这种情况下,尽可能明确地说明 平等 的含义是有帮助的。 在软件工程中,以正确的方式提出问题通常会使答案显而易见。

考虑到这一点,这里有 3 个数组相等的定义以及如何检查它们。

长度相同,每个值相等

一种比较方法 ab 正在检查是否每个值 a 严格等于对应的值 b, 如果数组的所有元素都是基元而不是对象,则此方法效果很好。

const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [1, 2, 3];

function arrayEquals(a, b) {
  return Array.isArray(a) &&
    Array.isArray(b) &&
    a.length === b.length &&
    a.every((val, index) => val === b[index]);
}

arrayEquals(a, b); // false
arrayEquals(a, c); // true

深度平等 POJO

以前的 arrayEquals() 函数适用于原始值,但如果您想按值比较对象,则效果不佳。

const a = [{ answer: 42 }, { powerLevel: 9001 }];
const b = [{ answer: 42 }, { powerLevel: 9001 }];

// false, because { answer: 42 } !== { answer: 42 }, different references
arrayEquals(a, b);

考虑对象值的一种巧妙方法是比较数组 JSON.stringify() 输出。

const a = [{ answer: 42 }, { powerLevel: 9001 }];
const b = [{ answer: 42 }, { powerLevel: 9001 }];
const c = [{ answer: 42 }, { password: taco }];

JSON.stringify(a) === JSON.stringify(b); // true
JSON.stringify(a) === JSON.stringify(c); // false

这种方法很方便,因为它需要最少的代码并且不需要外部库。 然而比较 JSON.stringify() 输出有一个不幸的边缘情况,根据您的用例,这可能是一个问题。 自从 undefined 不是有效的 JSON 值,以下数组具有相同的 JSON.stringify() 输出,因为 JSON.stringify()转换 undefinednull

const a = [undefined];
const b = [null];

使用 Lodash 的 isEqual()

除了 null 对比 undefined 怪癖,比较 JSON.stringify() 输出也不考虑对象类型。 JSON.stringify() 是有关,一个对象与 toJSON() 返回 42 的函数与数字 42 相同。

const a = [{ toJSON: () => 42 }];
const b = [42];

JSON.stringify(a); // [42]
JSON.stringify(b); // [42]

同样,自定义对象与 POJO 相同:

class MyClass {
  constructor(obj) {
    Object.assign(this, obj);
  }
}

const a = [new MyClass({ answer: 42 })];
const b = [{ answer: 42 }];

JSON.stringify(a) === JSON.stringify(b); // true

Lodash 的 isEqual()function 另一方面:

const _ = require(lodash);

class MyClass {
  constructor(obj) {
    Object.assign(this, obj);
  }
}

const a = [new MyClass({ answer: 42 })];
const b = [{ answer: 42 }];

_.isEqual(a, b); // false

Lodash 的 isEqual() 如果您需要检查对象是否具有相同的类的所有花里胡哨的功能,那么函数就是您要走的路。JSON.stringify() 方法适用于 POJO,只要确保您考虑到 null 并且仅将其与受信任的数据一起使用 – toJSON() 可能是一个安全漏洞。

© 版权声明
评论 抢沙发

请登录后发表评论