为什么我的2对象深度比较失败了?

时间:2017-09-29 06:30:09

标签: javascript lodash

我试图使用深度比较比较2个对象,而比较我想忽略一些属性。

当我在对象的两侧都有忽略属性时,我的比较是成功的。

但是当我想忽略第二个对象中的1个属性时,我遇到了问题。

在我的 objA和objB 中,我想忽略 isParent和位置属性,但由于我在objB中没有位置属性,因此我的对象比较失败。

但是我不明白为什么我会变错,因为我已经指定了要忽略的位置属性。

var objA = {
  isParent: true,
  foo: {
    location: "abc",
    bar: "foobar"
  }
};

var objB = {
  isParent: false,
  foo: {
    bar: "foobar"
  }
};

var comparator = function(left, right, key) {
  if (key === 'isParent' || key === 'location') return true;//ignore isParent and location property while comparing 2 object
  else return undefined;              
}

var isEqual = _.isEqualWith(objA, objB, comparator);

console.log(isEqual); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

3 个答案:

答案 0 :(得分:3)

使用omit功能忽略不需要的属性,然后进行比较

var objA = {
  isParent: true,
  foo: {
    location: "abc",
    bar: "foobar"
  }
};

var objB = {
  isParent: false,
  foo: {
    bar: "foobar"
  }
};

var isEqual = _.isEqual(
  _.omit(objA, ['isParent', 'foo.location']), 
  _.omit(objB, ['isParent', 'foo.location'])
);

console.log(isEqual); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

答案 1 :(得分:1)

您可以编写自己的比较功能:

逻辑:

  • 创建一个函数,该函数包含两个将要比较的对象和一个要忽略的键的数组(ignoreKeys)。
  • 从两个对象获取所有密钥,合并它们,然后将它们过滤为新变量(keys )。
    • 如果keys中存在当前密钥,请忽略它。
    • 如果ignoreKeys中存在当前密钥,请将其忽略
    • 别推它。
  • 现在循环遍历这些键并检查比较:
    • 如果当前值的类型为'object',请使用递归并再次启动该过程。
    • 否则,比较这些值并返回比较。

由于必须对keys中的所有密钥执行此操作,因此您可以使用Array.every

<强>示例

function compareObject(obj1, obj2, ignoreProps){
  var temp = Object.keys(obj1).concat(Object.keys(obj2)).sort();
  var keys = temp.reduce(function(p,c) {
    if(p.indexOf(c) < 0 && ignoreProps.indexOf(c) < 0) {
      p.push(c);
    }
    return p;
  }, []);
  
  return keys.every(function(key){
    var t1 = typeof(obj1[key])
    var t2 = typeof(obj2[key])
    if(t1 === t1) {
      switch(t1) {
        case 'object': 
          if(obj1[key] !== null && obj2[key] !== null)
            return compareObject(obj1[key], obj2[key], ignoreProps);
          else
            return obj1[key] === obj2[key];
        default: return obj1[key] === obj2[key];
      }
    }
  })
}

var objA = {
  isParent: true,
  foo: {
    location: "abc",
    bar: "foobar",
    test: {
      location: 'bla',
      test1: {
        location: 'bla bla',
        value: null
      }
    }
  }
};

var objB = {
  isParent: false,
  foo: {
    bar: "foobar",
    test: {
      location: 'new',
      test1: {
        location: 'new new',
        value: null
      }
    }
  }
};

var ignoreProperties = ['isParent', 'location'];

console.log(compareObject(objA, objB, ignoreProperties));

答案 2 :(得分:1)

您可以获取给定对象的所有键并迭代并检查是否

  • 是无值检查(忽略)的关键,
  • 具有相同的值或
  • 这两个值都是真实的和对象,而check的调用会返回一个真值。

要忽略的属性的键被收集在一个对象中。

&#13;
&#13;
function check(o, p) {
    var keys = [...new Set(Object.keys(o).concat(Object.keys(p)))];

    return keys.every(k => noValueCheck[k]
        || o[k] === p[k]
        || o[k] && p[k] && typeof o[k] === 'object' && typeof p[k] === 'object' && check(o[k], p[k])
    );
}

var noValueCheck = { isParent: true, location: true },
    objA = { isParent: true, foo: { location: "abc", bar: "foobar" } },
    objB = { isParent: false, foo: { bar: "foobar" } };

console.log(check(objA, objB));
&#13;
&#13;
&#13;