js中判断Object、Array、Function等引用类型对象是否相等,引用类型无法直接使用 == 或=== 取得期待结果。
法一:需要一个迭代的compare函数转化成原始类型进行比较
function compare(a,b){ var pt = /undefined|number|string|boolean/, fn = /^(function\s*)(\w*\b)/, cr = "constructor", cn = "childNodes", pn ="parentNode", ce = arguments.callee; if(pt.test(typeof a) || pt.test(typeof b) || a === null || b === null){ return a === b || (isNaN(a) && isNaN(b)); //为了方便,此处假定NaN == NaN } if(a[cr] !== b[cr]){ return false; } switch(a[cr]){ case Date : { return a.valueOf() === b.valueOf(); }; case Function : { return a.toString().replace(fn,'$1') === b.toString().replace(fn,'$1'); //硬编码中声明函数的方式会影响到toString的结果,因此用正则进行格式化 }; case Array : { if(a.length !== b.length){ return false; } for(var i=0;i<a.length;i++){ if(!ce(a[i],b[i])){ return false; } } break; }; default : { var alen = 0, blen = 0, d; if(a === b){ return true; } if(a[cn] || a[pn] || b[cn] || b[pn]){ return a === b; } for(d in a){ alen++ ; } for(d in b){ blen++; } if(alen !== blen){ return false; } for(d in a){ if(!ce(a[d],b[d])){ return false; } } break; }; } return true; } console.log(compare({},{a:1})); //false console.log(compare({a:1},{b:2})); //false console.log(compare({b:2,a:1},{a:1,b:2})); //true console.log(compare({a:function(){return false;},b:2},{a:function(){return false;},b:2})); //true console.log(compare([],[])); //true console.log(compare([2,1],[1,2])); //false console.log(compare(function(){alert(1)},function(){})); //false console.log(compare(function aaa(){alert(1)},function(){alert(1)})); //true console.log(compare(document.getElementsByTagName("a")[0],document.getElementsByTagName("a")[1])); //true console.log(compare(document.getElementsByTagName("a")[0],document.getElementsByTagName("a")[0])); //true
法二:直接检测Array或Object的 用arguments.callee
function equal(objA, objB) { if (typeof arguments[0] != typeof arguments[1]) return false; console.log(arguments[0],arguments[1]); //数组 if (arguments[0] instanceof Array) { if (arguments[0].length != arguments[1].length) return false; var allElementsEqual = true; for (var i = 0; i < arguments[0].length; ++i) { if (typeof arguments[0][i] != typeof arguments[1][i]) return false; if (typeof arguments[0][i] == 'number' && typeof arguments[1][i] == 'number') allElementsEqual = (arguments[0][i] == arguments[1][i]); else allElementsEqual = arguments.callee(arguments[0][i], arguments[1][i]); //递归判断对象是否相等 } return allElementsEqual; } //对象 if (arguments[0] instanceof Object && arguments[1] instanceof Object) { var result = true; var attributeLengthA = 0, attributeLengthB = 0; for (var o in arguments[0]) { //判断两个对象的同名属性是否相同(数字或字符串) if (typeof arguments[0][o] == 'number' || typeof arguments[0][o] == 'string') result = eval("arguments[0]['" + o + "'] == arguments[1]['" + o + "']"); else { //如果对象的属性也是对象,则递归判断两个对象的同名属性 //if (!arguments.callee(arguments[0][o], arguments[1][o])) if (!arguments.callee(eval("arguments[0]['" + o + "']"), eval("arguments[1]['" + o + "']"))) { result = false; return result; } } ++attributeLengthA; } for (var o in arguments[1]) { ++attributeLengthB; } //如果两个对象的属性数目不等,则两个对象也不等 if (attributeLengthA != attributeLengthB) result = false; return result; } return arguments[0] == arguments[1]; } var a = {Name:"YuanXP",Id:9,Go:{a:'1',b:'2'}}; var b = {Id:9,Name:"YuanXP",'Go':{a:'1',b:'2'}}; var c= equal(a, b); console.log(c);