Javascript-deepEqual比较

Javascript-deepEqual比较,javascript,recursion,Javascript,Recursion,问题(来自雄辩的Javascript第二版,第4章,练习4): 编写一个函数deepEqual,它接受两个值并仅当它们 是相同的值或具有相同特性的对象,其值也是相同的 与对deepEqual的递归调用相比,等于 测试用例: var obj = {here: {is: "an"}, object: 2}; console.log(deepEqual(obj, obj)); // → true console.log(deepEqual(obj, {here: 1, object: 2})); //

问题(来自雄辩的Javascript第二版,第4章,练习4):

编写一个函数deepEqual,它接受两个值并仅当它们 是相同的值或具有相同特性的对象,其值也是相同的 与对deepEqual的递归调用相比,等于

测试用例:

var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true
我的代码:

var deepEqual = function (x, y) {
  if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
    if (Object.keys(x).length != Object.keys(y).length)
      return false;
    for (var prop in x) {
      if (y.hasOwnProperty(prop))
        return deepEqual(x[prop], y[prop]);
    /*This is most likely where my error is. The question states that all the values
    should be checked via recursion; however, with the current setup, only the first
    set of properties will be checked. It passes the test cases, but I would like
    to solve the problem correctly!*/
      }
    }
  else if (x !== y)
    return false;
  else
    return true;
}
我想我已经把大概的想法记下来了;但是,正如我在注释中所述,程序不会检查对象中的第二个属性。我觉得我有一个结构/逻辑问题,只是以错误的方式使用递归,因为我最初打算循环遍历属性,使用递归比较第一个属性的值,然后继续循环到下一个属性并再次比较。虽然,我不确定这是否可能


我考虑了很多,尝试了几种不同的方法,但这是迄今为止我得到的最正确的答案。任何可能的提示都可以为我指出正确的方向吗?

您可以在for循环之外使用一个变量来跟踪比较:

var allPropertiesEqual = true;
for (var prop in x) {
    if (y.hasOwnProperty(prop)) {
        allPropertiesEqual = deepEqual(x[prop], y[prop]) && allPropertiesEqual;
    } else {
        allPropertiesEqual = false;
    }
}
return allPropertiesEqual;
前面的示例不是有意优化的。因为您正在比较对象,所以您知道,一旦发现不相等项,就可以
返回false
,并且可以在所有先前选中的属性相等时继续循环:

for (var prop in x) {
    if (y.hasOwnProperty(prop)) {
        if (! deepEqual(x[prop], y[prop]) )
            return false; //first inequality found, return false
    } else {
        return false; //different properties, so inequality, so return false
    }
}
return true;

正如您所怀疑的,您正在返回第一个看到的属性的匹配项。如果该属性不匹配,则应返回
false
,否则继续查找

另外,如果在
y
上未找到
prop
属性,则返回
false
(即计数匹配,但实际属性不匹配)

如果所有属性都匹配,则返回
true

var deepEqual = function (x, y) {
  if (x === y) {
    return true;
  }
  else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
    if (Object.keys(x).length != Object.keys(y).length)
      return false;

    for (var prop in x) {
      if (y.hasOwnProperty(prop))
      {  
        if (! deepEqual(x[prop], y[prop]))
          return false;
      }
      else
        return false;
    }

    return true;
  }
  else 
    return false;
}
var deepEqual=函数(x,y){
如果(x==y){
返回true;
}
else if((typeof x==“object”&&x!=null)和&(typeof y==“object”&&y!=null)){
if(Object.keys(x).length!=Object.keys(y).length)
返回false;
用于(x中的var prop){
如果(y.hasOwnProperty(道具))
{  
如果(!deepEqual(x[prop],y[prop]))
返回false;
}
其他的
返回false;
}
返回true;
}
其他的
返回false;
}
var obj={here:{is:“an”,other:“3”},object:2};
控制台日志(deepEqual(obj,obj));
// → 真的
log(deepEqual(obj,{here:1,object:2}));
// → 假的
log(deepEqual(obj,{here:{is:“an”},object:2}));
// → 假的
log(deepEqual(obj,{here:{is:“an”,other:“2”},object:2}));
// → 假的
log(deepEqual(obj,{here:{is:“an”,other:“3”},object:2}));

// → 没错
我对JS很陌生,但这是我解决问题的方法:

function deepEqual(obj1, obj2) {
if (typeof obj1 === "object" && typeof obj2 === "object") {
    let isObjectMatch = false;
    for (let property1 in obj1) {
        let isPropertyMatch = false;
        for (let property2 in obj2) {
            if (property1 === property2) {
                isPropertyMatch = deepEqual(obj1[property1], obj2[property2])
            }

            if(isPropertyMatch){
                break;
            }
        }

        isObjectMatch  = isPropertyMatch;

        if (!isObjectMatch) {
            break;
        }
    }

    return isObjectMatch;
} else {
    return obj1 === obj2;
}
}
以下是我的测试:

var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}))
// → true
console.log(deepEqual(obj, {object: 2, here: {is: "an"}}));
// → true
console.log(deepEqual(obj, {object: 1, here: {is: "an"}}));
// → false
console.log(deepEqual(obj, {objectt: 2, here: {is: "an"}}));
// → false
console.log(deepEqual(2, 2));
// → true
console.log(deepEqual(2, 3));
// → false
console.log(deepEqual(2, null));
// → false
console.log(deepEqual(null, null));
// → false
console.log(deepEqual(obj, null));
// → false

感觉这个版本更可读(更容易理解)。不过,逻辑与上面的答案非常相似。(这次是ES6)

功能相等(obj1、obj2){
if(obj1==obj2)//它只是同一个对象,不需要比较。
返回true;
if(isPrimitive(obj1)和&isPrimitive(obj2))//比较原语
返回obj1==obj2;
if(Object.keys(obj1).length!==Object.keys(obj2).length)
返回false;
//比较具有相同关键帧数的对象
用于(输入obj1)
{
如果(!(输入obj2))返回false;//其他对象没有此属性
如果(!deepEqual(obj1[key],obj2[key])返回false;
}
返回true;
}
//检查值是否为原始值
函数isPrimitive(obj)
{
返回(obj!==对象(obj));
}
顺便说一句,有一个欺骗版的deep equal,它像一个符咒一样工作),但是,它的速度大约慢了1.6倍

正如zero298所注意到的,这种方法对属性排序很敏感,不应认真对待


我刚读完这一章,也想展示一下我的作品

我的缺陷(如果还有更多的,请告诉我)是对象属性也必须按精确顺序排列。我更喜欢保罗和丹尼的解决方案

//深度相等
常数deepEqual=(x,y)=>{
const xType=x的类型;
常数y类型=y的类型;
if(xType==='object'&&yType==='object'&&&(x!==null&&y!==null)){
const xKeys=Object.keys(x);
const yKeys=Object.key(y);
常数xValues=对象值(x);
常量y值=对象值(y);
//检查两个数组的长度
如果(xKeys.length!==yKeys.length)返回false;
//比较键
对于(i=0;i{
return`For:
${JSON.stringify(x)}

${JSON.stringify(y)}
>>${deepEqual(x,y)}`; }; //将结果打印到 const resultDivs=document.querySelectorAll('.result'); resultDivs[0]。innerHTML=result(obj1,obj2); resultDivs[1].innerHTML=result(obj3,obj4); resultDivs[2]。innerHTML=r
function cheatDeepEqual(obj1, obj2)
{
    return JSON.stringify(obj1) === JSON.stringify(obj2);
}
function deepEqual(elem1, elem2) {
    if(elem1 === elem2) {
        return true;
    }
    if(typeof elem1 == 'object' && typeof elem2 == 'object' && elem1 != null && elem2 != null) {
      if(Object.keys(elem1).length == Object.keys(elem2).length) {
          for(let key of Object.keys(elem1)) {
              if(elem2.hasOwnProperty(key) != true) {
                  return false;
              }
          }
          for(let key of Object.keys(elem1)) {
              if(typeof elem1[key] == 'object' && typeof elem2[key] == 'object' && typeof elem1[key] != null && typeof elem2[key] != null) {
                  return deepEqual(elem1[key], elem2[key]);
              }
              else {
                if(elem1[key] !== elem2[key]) {
                    return false;
                }
              }
          } else {
            return false;
          }
        }
      }
    else {
        return false;
    }
    return true;
  }