JavaScript: 深度比较

10
我在查看这个问题Javascript深度比较,但提问者的解决方案并没有说服我,所以我试图分析问题并得出了以下结论。
var obj = {here: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1}));
// → false
console.log(deepEqual(obj, {here: 2}));
// → true
function deepEqual(a,b)
{
  if( (typeof a == 'object' && a != null) &&
      (typeof b == 'object' && b != null) )
  {
     var count = [0,0];
     for( var key in a) count[0]++;
     for( var key in b) count[1]++;
     if( count[0]-count[1] != 0) {console.log('1');return false;}
     for( var key in a)
     {
       if(!(key in b) || !deepEqual(a[key],b[key])) {console.log('2');return false;}
     }
     for( var key in b)
     {
       if(!(key in a) || !deepEqual(b[key],a[key])) {console.log('3');return false;}
     }  
  }
  console.log('a:'+a+' b:'+b);
  return a===b;
}
obj === { here:2 }

这段代码未通过最后一个测试(console.log(deepEqual(obj, {here: 2}))),但是考虑到对象具有相应的相等键和值时即使在内存中是不同的实例也被认为是深度相等的逻辑并不让我信服。我的“解决方案”存在问题还是错误在于练习的假设?链接中提到的代码是否有效?hikinthru忘记提及的资源(http://eloquentjavascript.net/04_data.html#exercise_deep_compare)。

你的问题不太清楚。你是在说你不同意深度相等应该意味着什么吗? - Frank Tan
这是我询问的一部分。我的提议解决方案是错误的,还是问题出在其他地方?最后一行表明,对于浏览器来说,即使具有相同键和对应值的对象也不是严格相等的。如果问题存在问题,请告诉我,我会删除它。 - zenwaichi
你的函数在确认两个对象具有相同属性后,从未执行return true - Bergi
1个回答

19

“深度相等”是你所链接问题所讨论的内容,与“严格相等”是两个不同的概念。“深度相等”意味着,如你所说,“键和值相等”。对于对象,“严格相等”意味着“同一实例”。严格相等蕴含深度相等,但对象可以在不严格相等的情况下深度相等。

你的代码有些低效,因为你只需要一个循环,但如果你在else块中检查a === b并在for循环后return true,它将会正确执行。这是因为你应该将对象与字符串和数字等基本值分开处理。出于清晰起见,我已删除了一些日志,并尽量保持你的风格。


(Tips: "对象" can be translated as "object" or "objects," depending on the context.)

var obj = {here: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1}));
// → false
console.log(deepEqual(obj, {here: 2}));
// → true
console.log(obj === { here:2 });
// → false
function deepEqual(a,b)
{
  if( (typeof a == 'object' && a != null) &&
      (typeof b == 'object' && b != null) )
  {
     var count = [0,0];
     for( var key in a) count[0]++;
     for( var key in b) count[1]++;
     if( count[0]-count[1] != 0) {return false;}
     for( var key in a)
     {
       if(!(key in b) || !deepEqual(a[key],b[key])) {return false;}
     }
     for( var key in b)
     {
       if(!(key in a) || !deepEqual(b[key],a[key])) {return false;}
     }
     return true;
  }
  else
  {
     return a === b;
  }
}


最好加上一个最大深度指示器。谢谢。 - myuce
1
a === b 应该真正使用 Object.is(a, b) - Sebastian Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接