两个相等数组的比较失败

时间:2015-11-02 23:07:38

标签: javascript arrays google-chrome debugging comparison

通常,在解决StackOverflow社区问题时,我会尝试描述我的问题 但是现在很难说清楚。请看下面的图片:

一般来说,colors在很多方面都会发生多次变化; initial是常量,用于检查当前状态是否等于初始状态(如果没有,则取消所有更改)。
问题看起来很简单,但我一直坚持下去。怎么可能,两个相等的数组不是总是相等

我不知道在没有提供整个项目代码的情况下添加什么, - 所以请问我会回答。

5 个答案:

答案 0 :(得分:2)

JavaScript对象比较(包括数组对象之间的比较)仅比较参考值。两个不同的对象永远不会彼此相等,无论它们是什么样的。

您当然可以根据自己的标准编写自己的数组比较函数,以确定一个数组与另一个数组相等。如果数组应包含相同顺序的相同值,则视为相等,例如:

function arraysEq(a1, a2) {
  if (a1.length != a2.length) return false;
  for (var i = 0; i < a1.length; ++i)
    if (a1[i] !== a2[i]) return false;
  return true;
}

请注意,这只是一个例子;它不应被视为“如何比较两个阵列”问题的一般解决方案。

答案 1 :(得分:2)

ECMAscript中的数组也只是Object的一种特殊形式。这反过来意味着,如果您使用array1array2=====进行比较,则有效地比较两个对象引用,而不是数组本身及其内容。

实际上,如果可以保证内容始终是字符串,那么join数组的第二种方法并比较结果并不错。否则你必须循环数组,单独比较每个值,当然还要比较那些数组的.length

答案 2 :(得分:2)

Javascript中的==运算符不会比较两个数组或对象的内容。相反,它只是比较两个数组或对象是否实际上是同一个对象。如果要查看两者是否包含相同的内容,可以创建自己的比较功能。对包含字符串的数组执行此操作的一种可能方法是使用.join()

colors.join("") === initial.join("")

对于所有可能的数组内容,这并非完全万无一失,但如果您知道数组只包含字符串并且字符串本身不包含逗号,那么这就是一个快捷方式。还可以编写更强大的内容比较。对于数组的一级深度比较,您可以使用:

function compareArrays(a, b) {
    if (typeof a.length === "number" && a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

对于每个数组可能包含其他数组或对象的深度比较,您还希望比较这些数组或对象的内容,那么您需要一个可以深入比较对象属性和数组元素的递归解决方案。

您可以使用以下内容对对象和数组进行深入比较:

function compareObjects(a, b) {
    // if both are objects, then do a deep comparison of all properties
    if (typeof a === "object" && typeof b === "object") {
        var aKeys = Object.keys(a).sort(), bKeys = Object.keys(b).sort();
        var prop;
        if (!compareArrays(aKeys, bKeys)) {
            return false;
        }
        // here we know the two objects have the same keys, check values now
        for (var i = 0; i < aKeys.length; i++) {
            prop = aKeys[i];
            if (typeof a[prop] === "object" && typeof b[prop] === "object") {
                if (!compareObjects(a[prop], b[prop])) {
                    return false;
                }
            } else if (a[prop] !== b[prop]) {
                return false;
            }
        }
        return true;
    } else {
        // not both objects so just do straight equality
        return a === b;
    }
}

function compareArrays(a, b) {
    if (typeof a.length === "number" && a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

这将允许您比较在其中包含对象的嵌套结构,并比较除了这样的数组之外的普通对象:

var a = {foo: [1,2,3,["a","b","c"]], fee: {a: "1"}};
var b = {fee: {a: "1"}, foo: [1,2,3,4,["a","b","c"]]};

注意:这会比较对象或数组的公开可枚举属性。它不比较自定义形成对象的私有(例如闭包)变量(比如创建闭包的构造函数)。对于那些,比较它们的唯一方法是使用自定义比较方法,可以访问对象本身的私有数据。

注意:这不适用于包含循环引用的对象或数组(DOM对象因循环引用而臭名昭着)。通过跟踪已经在数组或集合中进行比较的所有引用,并且如果已经在比较它们的过程中再次没有再次引用它,可以使它与循环引用一起工作。

答案 3 :(得分:1)

这是javascript等于(==)运算符的工作原理:

以及严格同等的工作原理(===):

来自JavaScript Equality Table的图片。

答案 4 :(得分:1)

JavaScript 中,我们有[] === []; // false因为所有对象都通过引用进行了相等的测试,您可以看到此here <的规范sup> (7)here (1.f)

您可以使用Array.prototype.every

编写一个函数来进行所需的测试
function equivArray(a, b) {
    return a.length === b.length && a.every(function (e, i) {return e === b[i];});
}

现在

var foo = ['a', 'b', 1, 2],
    bar = ['a', 'b', 1, 2];

equivArray(foo, bar); // true