【问题标题】:Beginner - Deep comparaison in Javascript初学者 - Javascript 中的深度比较
【发布时间】:2017-09-08 12:17:25
【问题描述】:

免责声明:我是 JS 的初学者

我正在阅读 Eloquent Javascript,其中一项练习是深入比较 JS 中的对象。

有一些对象定义如下:

var obj = {here: {is: "an"}, object: 2};

你应该检查它们的内容是否相等。 然后是3个测试:

console.log(deepEqual(obj, obj)); // supposed to return true
console.log(deepEqual(obj, {here: 1, object: 2})); // supposed to return false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2})); // supposed to return true

这是我对深度相等方法的实现。为了简化,我假设比较的对象具有相同的结构,它们在现实生活中不会,但我的方法应该返回 false(我认为)

function deepEqual(obj1,obj2)
{
console.log("========");
  for(prop in obj1)
  {
    console.log(prop);
    if (typeof(prop)=="object" && prop!=null)
    {
        console.log("Inspecting object ", obj1[prop],obj2[prop]);
        if (!deepEqual(obj1[prop],obj2[prop]))
        {
        return false;
        }
    }
    else
    {
      console.log("Inspecting property ",prop,'[',obj1[prop],'][',obj2[prop],']');
      if (obj1[prop]!=obj2[prop])
      { 
        console.log("Different property");
        return false;
      }
    }
  }
  return true;
}

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

分别返回真、假和……假!

这是输出:

========
here
Inspecting property  here [ {is: "an"} ][ {is: "an"} ]
object
Inspecting property  object [ 2 ][ 2 ]
true
========
here
Inspecting property  here [ {is: "an"} ][ 1 ]
Different property
false
========
here
Inspecting property  here [ {is: "an"} ][ {is: "an"} ]
Different property
false

有两点我不明白:

  • 为什么总是转到“检查属性”而不是“检查对象”? {is: "an"} 不是一个对象吗?
  • 为什么表达式 "obj1[prop]!=obj2[prop]" 为真,尽管根据日志,它们都等于:{is: "an"}?

仅供参考,书中的参考实现是:

function deepEqual(a, b) {
  if (a === b) return true;

  if (a == null || typeof a != "object" ||
      b == null || typeof b != "object")
    return false;

  var propsInA = 0, propsInB = 0;

  for (var prop in a)
    propsInA += 1;

  for (var prop in b) {
    propsInB += 1;
    if (!(prop in a) || !deepEqual(a[prop], b[prop]))
      return false;
  }

  return propsInA == propsInB;
}

对我来说,第一个 for 循环只计算 A 中有多少属性对吗? 我完全被第二个 for 循环( for (var prop in b) )弄糊涂了……

编辑:非常感谢各位的回答!我不知道该接受哪一个,因为两者都对我有很大帮助:-/

【问题讨论】:

    标签: javascript


    【解决方案1】:

    prop(在您的 for (prop in obj) 循环中)不是一个值 - 它是一个键 (for in loop on MDN)。使用for in 循环时,您引用的值如下:

    for (var key in obj) {
        var value = obj[key];
    }
    

    关于第二个问题:

    为什么表达式“obj1[prop]!=obj2[prop]”是真的,虽然, 根据日志,它们都等于: {is: "an"} ?

    请注意,在比较两个对象(或任何其他非原始值)时,它们是按引用进行比较,而不是按值进行比较:

    var obj1 = { name: true };
    var obj2 = { name: true };
    obj1 === obj2;
    -> false (obj1 and obj2 are different objects)
    
    var obj3 = { name: true };
    var obj4 = obj3;
    obj3 === obj4;
    -> true (obj4 is basically a reference to obj3)
    

    旁注:JavaScrpt 中的一个好习惯是使用===(严格比较)运算符而不是==(抽象比较)。为什么?因为前者不会将比较值隐式转换为其他类型。 Javascript 的类型转换不是那么明显,所以最好还是坚持使用更可预测的操作符。在 JS 中使用严格比较通常是比较安全的方法。

    您可以阅读有关主题on MDN的更多信息。

    【讨论】:

    • 我认为 === 是指引用,== 是指价值?那么如何按价值进行比较?
    • 不,它不是这样工作的。您可以阅读我的旁注或直接转到comparison operators 上的文档
    • 至于 by value 比较 - 这就是您的 deepEqual 函数的基本用途(比较非原始值时)。原始值(如字符串或数字)总是按值进行比较 - ===== 之间的区别在于类型转换(在我的旁注中进行了解释)。
    • 好吧,所以在对象的情况下,如果两个操作数都引用同一个对象,则 === 返回 true 但是在原始类型(如字符串)的情况下,会比较内容。好的,我知道了。非常感谢!!!
    【解决方案2】:

    这一行是错误的:

    if (typeof(prop)=="object" && prop!=null)
    

    prop 是属性的键,它总是一个字符串,而不是属性的值。应该是:

    if (typeof(obj1[prop])=="object" && obj1[prop]!=null)
    

    【讨论】:

      【解决方案3】:

      我有一个很好的类比可能有助于解决这个问题:

      为什么表达式“obj1[prop]!=obj2[prop]”是真的,虽然, 根据日志,它们都等于: {is: "an"} ?

      我和我的兄弟可以说我们有同一个母亲。

      我和那边的那个人可以说我们有相同的车,因为我们都有一辆黑色的丰田凯美瑞。

      My Mother === My Brother's Mother  // true, she is really the same person.
      
      My car === Guy's car               // false, looks the same but 2 different cars
      
      obj !== {here: {is: "an"}, object: 2} // just looks the same
      

      === 是严格相等,例如"3" === 3 // false ... AND ...
      == 忽略 "3" == 3 // true 等数据类型

      【讨论】:

        猜你喜欢
        • 2016-11-18
        • 1970-01-01
        • 1970-01-01
        • 2021-10-10
        • 2017-03-27
        • 1970-01-01
        • 2015-10-15
        • 2011-05-27
        • 2023-03-25
        相关资源
        最近更新 更多