【问题标题】:How to test if two objects are the same with JavaScript?如何用 JavaScript 测试两个对象是否相同?
【发布时间】:2016-02-08 19:58:06
【问题描述】:

我需要一个函数:

function isSame(a, b){
} 

其中,如果 a 和 b 相同,则返回 true。
,我试过return a === b,但是我发现[] === []会返回false。
我希望这个函数可以给出一些结果:

isSame(3.14, 3.14);  // true  
isSame("hello", "hello"); // true  
isSame([], []); // true  
isSame([1, 2], [1, 2]); // true  
isSame({ a : 1, b : 2}, {a : 1, b : 2}); //true  
isSame([1, {a:1}], [1, {a:1}]);  //true

【问题讨论】:

  • 你真的认为isSame([1, 2], [2, 1]); 是真的吗?数组是有序的。这些不一样。
  • @jtbandes 我忘了,谢谢
  • @Pez:他可能想要一个自定义函数,而不仅仅是return a === b;
  • @wong2 - 如果 a 和 b 都引用同一个对象,您的 isSame() 是否返回 true,或者如果它们引用不同的对象但这些对象具有相同的编号,则返回 true具有相同属性名称和值的属性?原型也一样?这已在之前讨论过 - 参见,例如,stackoverflow.com/q/201183/615754

标签: javascript


【解决方案1】:

您可以嵌入Underscore.js 并使用_.isEqual(obj1, obj2)。 该函数适用于任意对象,并使用最有效的方法来测试给定对象是否相等。

【讨论】:

  • +1 - 这对我来说特别重要,因为我对下划线不是很熟悉,但我正在使用 Meteor(它带有 _)。
【解决方案2】:

最好的方法是使用 JSON 序列化程序。将两者序列化为字符串并比较字符串。

【讨论】:

  • 如果数组中的项目的顺序不同怎么办?这些列表包含相同的元素,但一旦序列化,它们看起来就不一样了。
  • @svanryckeghem 如果它们的顺序不同,它们就不一样了。数组是有序集合
  • @TheBrain - 如果对象包含方法怎么办? JSON 序列化器不会处理这个问题。此外,非数组对象的属性并没有真正的顺序,因此可能不会产生相同的 JSON 字符串(除非您编写了一个明确排序它们的 JSON 序列化程序)。最后,如果两个具有相同名称/值属性集的对象具有不同的原型,它们是否相等?
  • @Raynos - 这取决于“相同”对您意味着什么。作为开发人员,我可能想知道它们是否严格相同,或者它们是否等效。这是语义问题,而不是自然问题。这与通过引用或值知道两个对象是否相等没有太大区别。
  • 我的解决方案是针对您想要测试两个对象是否相同的情况。这意味着它们以相同的顺序具有相同的属性和相同的值。如果某件事,任何事情发生了变化,那么它们就不一样了。对于您在问题中提供的所有示例,序列化都有效。
【解决方案3】:

在 Crockford 的网站上有一些示例,改编自方案。具体来说,请查看:

function isEqual(s1, s2) {
    return isAtom(s1) && isAtom(s2) ? isEqan(s1, s2) :
            isAtom(s1) || isAtom(s2) ? false :
            isEqlist(s1, s2);
}

都可以在这里找到:

http://javascript.crockford.com/little.js

这是一个工作示例:

http://jsfiddle.net/FhGpd/

更新:

刚刚写了一些基于 OP 的测试用例。结果我需要修改 sub1 函数来检查

【讨论】:

    【解决方案4】:

    以下是可行的:

    function isSame(obj1, obj2, prefer){
    // Optional parameter prefer allows to only check for object keys and not both keys and values of an object
    var obj_prefer = prefer || "both"; 
    function checkArray(arr1, arr2){
        for(var i = 0, j = obj1.length; i<j; i++){
            if(obj1[i] !== obj2[i]){return false;}
        }
        return true;
    }
    
    function checkValues(obj_1, obj_2){
        for(var prop in obj_1){
            if(typeof obj_1[prop] === "function"){  // converting functions to string so that they can be matched
                obj_1[prop] = String(obj_1[prop]);
                obj_2[prop] = String(obj_2[prop]);
            }
    
            if(obj_1[prop] !== obj_2[prop]){ return false;}
        }
        return true;
    }
    // The built in === will check everything except when typeof object is "object"
    if ( typeof obj1 === "object"){
        // typeof Array is object so this is an alternative
        if((typeof obj1.push === "function") && (!obj1.hasOwnProperty('push'))){
            return checkArray(obj1, obj2);
            }
    
        else{
                if( obj_prefer !== "keys"){   // do not check for values if obj_prefer is "keys"
                    return checkValues(obj1, obj2);
                }
                var keys_1 = Object.keys(obj1);
                var keys_2 = Object.keys(obj2);
                if(!checkArray(keys_1, keys_2)){return false;}
    
                return true;
        }
    }
    
        // I thought undefined === undefined will give false but it isn't so you can remove it    
        if( typeof obj1 === "undefined" && typeof obj2 === "undefined" ){return true}
    
        if(typeof obj1 === "function"){
            return String(obj1) === String(obj2);
        }
    
            return obj1 === obj2;
    }
    console.log(isSame(2, 2));  //true
    console.log(isSame([1], [1])); // true
    

    由于它将函数转换为字符串以进行比较,因此请检查是否有空格,因为这可能会破坏事物:

    var func1 = function(){},
        func2 = function(){ }; // function with extra space
    isSame(func1, func2); // false
    

    您可以查看http://jsfiddle.net/webholik/dwaLN/4/ 亲自尝试。

    【讨论】:

      【解决方案5】:

      如果阅读此答案的人使用Angular.js,您可以使用angular.equals(obj1,obj2);

      根据docs

      确定两个对象或两个值是否相等。支持价值 类型、正则表达式、数组和对象。 如果两个对象或值中的至少一个被认为是等价的 以下是正确的:

      • 两个对象或值都通过=== 比较。
      • 两个对象或值都属于同一类型,并且通过将它们与 angular.equals 进行比较,它们的所有属性都相等。
      • 两个值都是NaN。 (在 JavaScript 中,NaN == NaN =&gt; false。但我们认为两个 NaN 相等)。
      • 两个值代表同一个正则表达式(在 JavaScript 中,/abc/ == /abc/ =&gt; false。但我们将两个正则表达式视为 当它们的文本表示匹配时相等)。
      • 在属性比较期间,函数类型的属性和名称以$ 开头的属性将被忽略。

      Scope 和 DOMWindow 对象仅通过标识 (===) 进行比较。

      【讨论】:

        猜你喜欢
        • 2012-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-26
        • 1970-01-01
        • 1970-01-01
        • 2010-11-19
        • 2022-12-04
        相关资源
        最近更新 更多