【问题标题】:Comparing Objects In JavaScript With A Recursion Function将 JavaScript 中的对象与递归函数进行比较
【发布时间】:2019-02-27 14:11:02
【问题描述】:

有人可以指导我了解这段代码中的递归函数吗?!deepEqual(a[key], b[key])。每次调用时它如何比较它的值?...

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

  let keysA = Object.keys(a), keysB = Object.keys(b);

  if (keysA.length != keysB.length) return false;

  for (let i = 0; i <= keysA.length -1; i++) {
     let key = keysA[i];
    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
  }

  return true;
}

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

我真的需要了解递归函数循环如何通过第二次调用而不在第一次检查时返回 true 而在第二次检查时返回 false if (a == null || typeof a != "object" || b == null || typeof b != "object") return false;

因为!deepEqual(a["is"], b["is"])) == !deepEqual("is", "is")) 的值,因此在第一次检查if (a === b) return true; 时应该返回true;。并在第二次检查 if (a == null || typeof a != "object" || b == null || typeof b != "object") return false; 时返回 false;,因为它不是对象。

不会阻止函数完成对 剩余属性?

谁能给我讲清楚?

let obj = {here: {is: "an", that: "at", name: "ola", here: {is: "as"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: {is: "an", that: "at", name: "ola", here: {is: "as"}, object: 3}));
// → false


//The only different property value is in the second argument's last property. 

【问题讨论】:

  • 如果你想比较两个对象然后把它们都转换成字符串然后检查相等性。
  • @ArifRathod 仅在 javascript 保证在字符串化时按字母顺序排列键时才有效。我不相信有这样的保证
  • 是的,你是对的,所以你应该先对对象进行排序,然后再进行比较。这将有效。我不认为我们应该写很长很复杂的逻辑来比较这两个对象。
  • 所以有人可以用我可以查看的分解代码形式或图表为我说明这一点。如果它是可见的,我会抓住这个想法
  • @Ola-Juwon 我想你会喜欢this Q&A

标签: javascript loops object recursion


【解决方案1】:

这很简单,让我们使用您问题中的示例来了解这段代码。

console.log(deepEqual(obj, obj));

在上述情况下,您正在比较相同的对象,而该对象又引用相同的内存位置,因此 if (a === b) return true; 被执行并返回 true。

console.log(deepEqual(obj, {here: {is: "as"}, object: 3}));

在此示例中,由于您要比较两个不同的对象,即不同的内存位置,因此,

  1. a === b 为假;现在我们继续比较对象键的值。
  2. a == null... 条件也满足,因此继续前进
  3. 键长度相同,所以我们进入 for 循环
  4. 对于 key = here obj.here 是一个对象,而 keysB 包含在此处;因此 deepEqual(a[here], b[here]) 被执行;第 1 步和第 2 步返回 false
  5. 现在在 for 循环中 deepequal a["is"] == b["is"] 返回 true。
  6. 对于 a["object"] == b["object"] 重复同样的操作,这不是真的,但是 a == null ||... get 被执行,因此返回 false。

console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));

为此,第二个示例中的所有步骤都以与第六步中购买相同的方式执行 a["object"] == b["object"] .

希望这可以清除所有步骤。

【讨论】:

  • 感谢 Roy 的解释....但是第二种情况呢?...我刚刚发布了一个类似于第一个的更新任务。请看一下并向我解释循环如何完成其​​所有运行,而不会在第一次检查时为合格的非对象值返回“true”或在第二次检查时返回“false”。我认为这将在没有完成的情况下结束程序......我真的很想了解这个检查是如何工作的......谢谢
  • 正如我在答案中提到的,第二个示例返回 false 因为 a["object"] != b["object"]; deepEqual(a["is"], b["is"])) 只有在第一个条件本身得到满足时才会返回 true。
  • 关于“不会阻止函数完成对剩余属性的检查吗?”不,它不会,因为对于调用 deepEqual 的控制台日志,它们将监听由它调用的函数的返回。并且在父级中调用的递归 deepEqual 只会将值返回给它的父级。因此,在父 deepEqual 中最终会基于“if (!keysB.includes('object') || !deepEqual(a['object'], b['object'])) return false;”返回 false;跨度>
猜你喜欢
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
  • 1970-01-01
相关资源
最近更新 更多