在原生 JavaScript 中对对象进行深度相等性检查👨👦
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
你是否曾经遇到过需要用 JavaScript 比较两个对象的情况?或许你发现 JavaScript 本身并没有提供解决这个问题的原生解决方案。在本教程中,我们将构建自己的实现方案!
你将了解到以下内容:
- 按值传递与按引用传递
- Object.keys() 方法
- 创建递归函数
你可以使用 Lodash 库,并使用其.isEqual方法对两个对象进行深度质量检查,但为了练习原生 JavaScript,最好自己创建解决方案。
假设我们有以下对象:
const obj1 = { name: 'Peter', stats: { points: 45, isActive: false }};
const obj2 = { name: 'Peter', stats: { points: 45, isActive: false }};
console.log(obj1 === obj2) // returns false
这两个对象完全相同,但 JavaScript 仍然返回 false。为什么?
这是因为在 JavaScript 中,像字符串和数字这样的基本类型是按其值进行比较的,而对象则是按引用进行比较的。
JavaScript 会将你创建的每个对象分配到内存中的不同位置。因此,即使你的对象内容完全相同,它们的引用(内存中的位置)也不同!
让我们开始创建函数。我们将创建一个名为 `function` 的函数compareObjects,它接受两个参数。首先,我们将检查这两个参数的类型是否相同,以及它们的值是否相同。
const compareObjects = (a, b) => a === b ? true : false;
const obj1 = { name: 'Peter', stats: { points: 45, isActive: false }};
compareObjects(obj1, obj1) // returns true
接下来,我们将添加检查,确认这两个参数的类型是否正确object,以及它们是否不是null值。为了避免类型转换,我们将使用 ` :` 而!=不是!==`:`。
const compareObjects = (a, b) => {
if (a === b) return true;
if (typeof a != 'object' || typeof b != 'object' || typeof a == null || typeof b == null) return false;
}
然后我们将检查两个对象的对象键的长度。如果它们的长度不同,我们就可以确定这两个对象不是同一个对象。
...
let keysA = Object.keys(a), keysB = Object.keys(b);
if (keysA.length != keysB.length) return false;
...
接下来,我们将使用循环遍历 keysA 数组的键for of。循环for of适用于数组,也for in适用于对象。
在这个循环中,我们将检查每个键是否存在于 keysB 数组中。此外,我们将比较每个键的值,并将这些值传递回我们的compareObjects函数,从而使我们的函数递归(调用自身)。
一旦我们的键值对中有一个不一致,循环和函数就会停止,并返回 false。
...
for (let key of keysA) {
if (!keysB.includes(key) || !compareObjects(a[key], b[key])) return false;
}
...
我们还要检查这两种方法是否相同,为此,我们将把函数转换为字符串,然后比较这两个值:
...
if (typeof a[key] === 'function' || typeof b[key] === 'function') {
if (a[key].toString() != b[key].toString()) return false;
}
...
如果循环检查了每个键并将每个嵌套值传递回它自己的函数,并且没有返回 false,那么只剩下一件事要做:返回 true!
完整功能:
const compareObjects = (a, b) => {
if (a === b) return true;
if (typeof a != 'object' || typeof b != 'object' || a == null || b == null) return false;
let keysA = Object.keys(a), keysB = Object.keys(b);
if (keysA.length != keysB.length) return false;
for (let key of keysA) {
if (!keysB.includes(key)) return false;
if (typeof a[key] === 'function' || typeof b[key] === 'function') {
if (a[key].toString() != b[key].toString()) return false;
} else {
if (!compareObjects(a[key], b[key])) return false;
}
}
return true;
}
感谢观看本教程,记得关注我获取更多内容哦!🧠
更多参考信息,请参阅《Eloquent JavaScript》一书。
文章来源:https://dev.to/sanderdebr/deep-equality-checking-of-objects-in-vanilla-javascript-5592
