做前端開發經常會遇到比較js對象是否相等的情況, 或者說其它問題往往會歸結到這個問題上來:比如對象數組的去重復。
網上看到過很多例子, 但是基本上都是那種比較簡單的對象結構, 而復雜的對象結構,比如對象嵌套對象的情況,還沒找到什么直接可以用的代碼。
所以今天,就花了點時間寫了一個函數實現這個功能, 也是方便自己日后使用, 當然也可以供大家參考。
注釋: 目前這個方法只適用於對象的屬性是基本類型和對象類型, 數組類型暫時還沒考慮, 后面有時間寫一個全的。----所以說下面的方法相當於比較兩個樹
第一個方法: 主要是將對象當做一個樹, 通過遞歸遍歷,將對象的所有屬性當做節點保存在二維數組中。(這個方法也適用於任何樹形數據結構的遍歷)
1 /* 2 * 遞歸方式將obj的所有樹路徑規整到二維數組中,第一維度表示路徑個數,第二個維度表示每條路徑上的節點 3 * 返回的是這個二維數組 4 */ 5 function getObjKeyPath(pathArry, paths, obj){ 6 for(var key in obj){ 7 var type = obj[key].constructor.name; //獲取屬性值對應的類型 8 if(type == "Object"){ 9 if(!paths){ 10 paths = []; 11 } 12 paths.push(key); 13 getObjKeyPath(pathArry, paths, obj[key]); 14 }else{ 15 if(!paths){ 16 pathArry.push([key]); 17 }else{ 18 var arry = paths.concat();//目的是復制數組 19 arry.push(key); 20 pathArry.push(arry); 21 } 22 } 23 } 24 return pathArry; 25 }
第二個方法就是實際的比較函數:
輸入參數就是兩個對象, 返回true表示兩個對象完全相等,反之不等.
主要想法就是,用上面的函數獲取到兩個對象的屬性樹, 然后以“葉子節點多的對象作為大樹”, 依次取大樹的葉子節點路徑在小數上的對應值, 一旦取不到或者取到不相等則兩個對象肯定不相等。
1 function CompareObj(obj1, obj2){ 2 var keys1 = getObjKeyPath([], null, obj1); 3 var keys2 = getObjKeyPath([], null, obj2); 4 var bigObj = null; 5 var smallObj = null; 6 var keys = null; 7 if(keys1.length >= keys2.length){ 8 bigObj = obj1; 9 smallObj = obj2; 10 keys = keys1; 11 }else{ 12 bigObj = obj2; 13 smallObj = obj1; 14 keys = keys2; 15 } 16 for(var i in keys){ 17 var val1 = bigObj; 18 var val2 = smallObj; 19 for(var j in keys[i]){ 20 var key = keys[i][j]; 21 val1 = val1[key]; 22 val2 = val2[key]; 23 if(val2 == undefined){ 24 return false; 25 } 26 } 27 if(val1 != val2){ 28 return false; 29 } 30 } 31 return true; 32 }
調用就很簡單了:
1 var flag = CompareObj(obj1, obj2);