开发者

How to test if two objects are the same with JavaScript?

I need a function:

function isSame(a, b){
} 

In which, if a and b are the same, it returns true.

, I tried return a === b, but I found that [] === [] will return false.

Some results that I expect this function can gave:

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


You could embed Underscore.js and use _.isEqual(obj1, obj2). The function works for arbitrary objects and uses whatever is the most efficient way to test the given objects for equality.


the best way to do that is to use a JSON serializer. serialize both to string and compare the string.


There are some examples, adapted from scheme, on Crockford's site. Specifically, check out:

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

It can all be found here:

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

Here is a working example:

http://jsfiddle.net/FhGpd/

Update:

Just wrote some test cases based on the OP. Turns out I needed to modify the sub1 function to check <= 0 not === 0 otherwise isEqual(3.14, 3.14) blew the stack. Also, isEqual does not work for object comparison, so you are on your own there. However, if you follow the examples on Crockford's site you will see how easy and fun it is to write recursive methods that could be used to check for object equality.


Here is something that can work:

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

Since it converts Functions into Strings to compare them, check out for spaces as that can break things:

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

You can check out http://jsfiddle.net/webholik/dwaLN/4/ to try it yourself.


If anyone reading this answer is using Angular.js, you can use angular.equals(obj1,obj2);

According to the docs:

Determines if two objects or two values are equivalent. Supports value types, regular expressions, arrays and objects. Two objects or values are considered equivalent if at least one of the following is true:

  • Both objects or values pass === comparison.
  • Both objects or values are of the same type and all of their properties are equal by comparing them with angular.equals.
  • Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal).
  • Both values represent the same regular expression (In JavaScript, /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual representation matches).
  • During a property comparison, properties of function type and properties with names that begin with $ are ignored.

Scope and DOMWindow objects are being compared only by identify (===).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜