雄辩的Javascript练习:深度比较



我正在学习JavaScript并尝试做这个练习:

编写一个函数deepEqual,该函数采用两个值,仅当它们是相同的值或具有相同属性的对象时才返回true,其中值 的属性与递归调用相比相等deepEqual.

若要确定是否应直接比较值(使用===运算符 为此(,或者比较它们的属性,您可以使用typeof运算符。 如果它为这两个值生成"对象",则应进行深入比较。 但是你必须考虑到一个愚蠢的例外:因为历史上 偶然,typeof null也产生了"对象"。

当您需要查看属性时,Object.keys函数将很有用 的对象进行比较。

这是我的解决方案,给了我truefalsefalse这是错误的

function deepEqual (a,b) {
if (a===b) return true;
if (typeof a=="object" && typeof b=="object") {         
let x=Object.keys(a), y=Object.keys(b);
if (x.lenght==y.lenght) {
for (key of x){
if (y.includes(key)){
if (a[key]===b[key]) return true;
else return false;
}
}
}
return true;
} 
}
let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));    
console.log(deepEqual(obj, {here: 1, object: 2}));
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));

这是正确的解决方案:

function deepEqual(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object") 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) || !deepEqual(a[key], b[key])) return false;
}
return true;
}

let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true

我真的无法理解我写的东西有什么问题以及如何解决它。

非常感谢您帮助菜鸟:)

以下是代码中的问题:

1(对象测试:

if (typeof a=="object" && typeof b=="object") {

这很好,但如果这个条件不成立怎么办?您没有任何处理这种情况的代码,因此该函数将返回undefined。它应该返回false

其次,JavaScript 中有一个奇怪的事情,这个问题已经警告过你——你应该考虑到它:

。因为历史的偶然,typeof null也产生了"对象"。

。因此,您需要对此进行单独的测试,因为null并不是真正的对象,并且当您将其视为对象时,代码会产生错误。

在您的代码中,null值将通过此if测试,然后执行Object.keys(null),这会触发异常。不应允许在其中使用null值。

2( 比较属性数量

if (x.lenght==y.lenght) {

有拼写错误。它不是lenght,而是length(2x(。 再说一次,如果这个条件不成立怎么办?除了该if之后return true之外,没有处理这种情况的代码,但您的函数应该返回false

3( 检查两个对象中是否存在属性

if (y.includes(key)){

此测试有效,但不是最佳测试。includes比仅检查该key in b要慢(遗憾的是参考解决方案也使用includes(。

和以前一样,如果这个条件不成立怎么办?该函数应立即退出循环并返回false,但这并没有发生...

4( 检查相同属性的值是否深度相等。

if (a[key]===b[key]) return true;

这种情况不会进行深入比较。这个问题已经告诉你在这里做什么:

。其中属性的值与递归调用相比相等deepEqual

因此,在这种情况下,您应该执行递归调用,以便以相同的方式比较任何嵌套对象。当这两个值是单独的对象时,只会falsea[key]===b[key]。但是,当这些对象具有相同的属性和相同的值时,条件确实应该true......这正是您的函数能够做的:所以在这里调用它。

其次,现在不是return true的时候,因为这将在不检查其他键的情况下退出循环,并且结果可能是负面的......而一个"负面"就足以使整体最终结果false.因此,虽然情况良好,但您应该继续循环。

5( 当值不同时

else return false;

是的,这是return false的正确时机.

6( 当所有测试成功时

return true;

这是唯一正确的return true,但您应该解决我答案中的第二句话,以便在长度不同时不会执行此陈述。

正确的代码

由于您已经有正确的代码可以比较,因此在此处重复该代码有点矫枉过正。