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 triedreturn 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 twoNaN
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
(===)
.
精彩评论