Javascript 修改的deepEqual函数不';行不通

Javascript 修改的deepEqual函数不';行不通,javascript,for-loop,recursion,Javascript,For Loop,Recursion,我在看来自于有说服力的Javascript练习的deepEqual比较函数。我想我可以通过将检查对象存在性和值相等性检查的if语句移动到第一个for..in循环而不是第二个循环来改进建议解决方案 我的推理是,如果对象没有匹配的属性或者它们的值不同,那么它将允许检查更早地失败,而不是等待在第二个循环中失败 更改无效,这是代码: function deepEqual(a, b){ if(a === b) return true; if(a === null || typeof a !== "

我在看来自于有说服力的Javascript练习的
deepEqual
比较函数。我想我可以通过将检查对象存在性和值相等性检查的
if
语句移动到第一个
for..in
循环而不是第二个循环来改进建议解决方案

我的推理是,如果对象没有匹配的属性或者它们的值不同,那么它将允许检查更早地失败,而不是等待在第二个循环中失败

更改无效,这是代码:

function deepEqual(a, b){
  if(a === b) return true;
  if(a === null || typeof a !== "object" ||
     b === null || typeof b !== "object")
    return false;

  var pA = pB = 0;
  //console.log('OBJECT detected vals:',a,b);
  for(var p in a){
    pA++;
    //console.log('pA:'+pA, p, a, (p in b));
    // MOVED THE IF STATEMENT INTO THIS LOOP INSTEAD OF THE
    // SECOND LOOP BELOW
    if(!(p in b) || !deepEqual(a[p], b[p]))  
      return false;
  }

  for(var p in b){
    pB++;
    //console.log('pB:'+pB, p, b, (p in a));
    //if(!(p in a) || !deepEqual(a[p], b[p]))
      //return false;
  }

  return pA === pB;
}

var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true WORKS
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false WORKS
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true, DOES NOT WORK, LOGS OUT FALSE...?
注释掉代码段中的console.log调用应呈现以下输出:

console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
OBJECT detected vals: Object {here: Object, object: 2} Object {here: Object, object: 2}
pA:1 here Object {here: Object, object: 2} true
OBJECT detected vals: Object {is: "an"} Object {is: "an"}
pA:1 is Object {is: "an"} true
pB:1 is Object {is: "an"} true <-- why is this being called here, pA loop hasn't finished???
pA:2 object Object {here: Object, object: 2} true
pB:2 here Object {here: Object, object: 2} true
pB:3 object Object {here: Object, object: 2} true
console.log(deepEqual(obj,{here:{is:},object:2}));
检测到的对象VAL:对象{此处:对象,对象:2}对象{此处:对象,对象:2}
pA:1 here对象{here:Object,Object:2}true
检测到的对象VAL:对象{is:“an”}对象{is:“an”}
pA:1是对象{is:“}真

pB:1是对象{is:“an”}true您被JavaScript的

问题在于这一行:

var pA = pB = 0;
当分解为多行时,它看起来像:

pB = 0;
var pA = pB;
这意味着
pB
不是用
var
声明的,因此是一个全局变量,而不是
deepEqual
的局部变量。这意味着它通过计算保留其值,因此具有错误的值

您的函数返回
false
,因为对于具有2个属性的顶级对象级别,
pB
以值
3
结束,而不是
2
,因为它记住了内部级别的计数,内部级别有1个属性
{is:“}
。其他两个测试之所以有效,是因为它们只检查一个级别的属性

如果将
pB
设为局部变量,则所有操作均有效:

函数深度相等(a,b){
如果(a==b)返回true;
如果(a==null | |类型a!==“对象”||
b==null | |类型b!==“对象”)
返回false;
//使两个变量都成为局部变量
var-pA=0;
var-pB=0;
对于(a中的var p){
pA++;
if(!(b中的p)| |!deepEqual(a[p],b[p]))
返回false;
}
对于(b中的var p){
pB++;
}
返回pA==pB;
}
var obj={here:{is:“an”},对象:2};

log(deepEqual(obj,{here:{is:“an”},object:2}))啊哈!谢谢我隐约知道这与此有关。我想我一定一直在尝试这样做:
var-pA,pB=pA=0。我的推理是将
if
条件移动到第一个循环声音吗?@Pineda不客气。只要在两个循环中都有
if
条件,就总体(基于最坏情况)效率而言,它不会真正改变任何东西。您的更改可能对某些特定情况有所帮助,但会降低其他情况的效率。基本上,您所做的是使
pA
pB
更重要,但是如果有人以相反的方式传递参数,那么使用初始不变的方法会更好。