深度比较(Eloquent Javascript第4章):代码在测试用例中失败

Deep Comparison (Eloquent Javascript Chapter 4): code fails a test case

本文关键字:代码 测试用例 失败 4章 比较 Eloquent Javascript 深度      更新时间:2023-09-26

我正在学习Eloquent Javascript书中的Javascript。我有点困惑于我的代码是如何在第4章(对象介绍)中的深度比较练习中失败的

目标

编写一个函数deepEqual,它接受两个值并返回true仅当它们具有相同值或是具有相同值的对象时与递归相比,其值也相等的属性调用deepEqual。

要确定是否按身份比较两件事(使用===运算符),或者通过查看它们的属性,可以使用运算符类型。如果它为两个值都生成"对象",则应该做一个深入的比较。

我的代码

function deepEqual(obj1, obj2)
{
    var truefalse = undefined;
    var type1 = typeof obj1;
    var type2 = typeof obj2;
// In case both are objects
    if(type1 == 'object' && type2 == 'object')
    {
        var prop1 = [];
        var prop2 = [];
        for(var prop in obj1)
            prop1.push(prop);
        for(var prop in obj2)
            prop2.push(prop); 
        // Test if both objects have the same number of properties
        if(prop1.length == prop2.length)
        {
            // Test if all properties between them have the same names,
            // by generating index for each property in prop1 against prop2
            var indexArray = [];
            for(var i = 0; i < prop1.length; i++)
            {
                var index = prop2.indexOf(prop1[i]);
                indexArray.push(index);
            };
            // If there's no "-1" anywhere in the indices generated
            // (all properties are named the same between them),
            // move on to value comparison for each property
            if(indexArray.indexOf(-1) == -1)
                {
                for(var event in obj1)
                    {
                        if(deepEqual(obj1[event], obj2[event]))
                            truefalse = true
                        else
                            truefalse = false;
                    };
                }
            // Different property names
            else
                truefalse = false;
        }
        // Different number of properties
        else
            truefalse = false;
    }
    // Either/both are not objects
    else
        truefalse = (obj1 === obj2);
    return truefalse;
}
console.log(deepEqual({here: 3, object: 1}, {object: 1, here: 2}))
// → true

我的问题

通过一些调试,我怀疑当首先比较here属性的值(3和2)时,它会向truefalse变量返回false,因为它们彼此不同。但是,当for(var event in obj1) {...}循环转到object属性时,我的truefalse变量被重写为true,因为两者具有相同的值。

如果这是正确的诊断,是否有任何方法可以纠正此错误?也许我应该使用or条件,但我就是想不出将它和for循环结合起来的方法。

谢谢你对这个初学者的帮助。

PS。在写这篇文章的时候,我意识到我本可以使用in测试来检查两个对象中的所有属性是否命名相同,但我现在太累了,无法编辑这篇文章。如果我的代码的那部分看起来很笨拙,我深表歉意。

通常,您应该假设函数返回true(equals),当发现任何差异时,立即返回false。

首先,更改truefalse的默认值。

var truefalse = true

然后,更换

for(var event in obj1)
{
    if(deepEqual(obj1[event], obj2[event]))
        truefalse = true
    else
        truefalse = false;
};

带有

for(var event in obj1)
{
    if(deepEqual(obj1[event], obj2[event]) == false)
        return false
};

现在它应该工作了!

Rgrds,