Làm thế nào để làm một so sánh sâu giữa 2 đối tượng với lodash?


309

Tôi có 2 đối tượng lồng nhau khác nhau và tôi cần biết liệu chúng có khác nhau về một trong các thuộc tính lồng nhau của chúng không.

var a = {};
var b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

Đối tượng có thể phức tạp hơn nhiều với các thuộc tính lồng nhau hơn. Nhưng đây là một ví dụ tốt. Tôi có tùy chọn để sử dụng các hàm đệ quy hoặc một cái gì đó với lodash ...



7
_.isEqual(value, other)Thực hiện so sánh sâu giữa hai giá trị để xác định xem chúng có tương đương không. lodash.com/docs#isEqual
Lukas Liesis

JSON.opesify ()
xgqfrms

10
JSON.opesify () sai: JSON.opesify ({a: 1, b: 2})! == JSON.opesify ({b: 2, a: 1})
Shl

Câu trả lời:


475

Một giải pháp dễ dàng và thanh lịch là sử dụng _.isEqual, thực hiện so sánh sâu:

var a = {};
var b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

_.isEqual(a, b); // returns false if different

Tuy nhiên, giải pháp này không cho thấy tài sản nào là khác nhau.

http://jsfiddle.net/bdkeyn0h/


2
Tôi biết rằng câu trả lời là khá cũ, nhưng tôi muốn thêm, điều đó _.isEqualcó thể khá khó khăn. Nếu bạn sao chép đối tượng và thay đổi một số giá trị trong đó thì nó vẫn sẽ hiển thị đúng, bởi vì tham chiếu là như nhau. Vì vậy, người ta nên cẩn thận khi sử dụng chức năng này.
oruckdeschel

23
@oruckdeschel nếu tham chiếu giống nhau, nó là cùng một đối tượng. do đó nó là bằng nhau. Đây là một con trỏ bị lừa không lodash. lodash là tuyệt vời.
anh chàng mograbi

265

Nếu bạn cần biết thuộc tính nào khác nhau, hãy sử dụng less () :

_.reduce(a, function(result, value, key) {
    return _.isEqual(value, b[key]) ?
        result : result.concat(key);
}, []);
// → [ "prop2" ]

36
Lưu ý rằng điều này sẽ chỉ xuất các thuộc tính khác nhau cấp đầu tiên. (Vì vậy, nó không thực sự sâu sắc trong ý nghĩa của việc xuất các thuộc tính khác nhau.)
Bloke

16
Ngoài ra, điều này sẽ không nhận các thuộc tính trong b mà không có trong a.
Ed Staub

3
_.reduce(a, (result, value, key) => _.isEqual(value, b[key]) ? result : result.concat(key), [])cho giải pháp ES6 một dòng
Dotgreg

1
Một phiên bản bao gồm khóa: valuelet edited = _.reduce(a, function(result, value, key) { return _.isEqual(value, b[key]) ? result : result.concat( { [key]: value } ); }, []);
Aline Matos

47

Đối với bất kỳ ai vấp phải chủ đề này, đây là một giải pháp hoàn chỉnh hơn. Nó sẽ so sánh hai đối tượng và cung cấp cho bạn khóa của tất cả các thuộc tính chỉ có trong object1 , chỉ trong object2 hoặc cả trong object1 và object2 nhưng có các giá trị khác nhau :

/*
 * Compare two objects by reducing an array of keys in obj1, having the
 * keys in obj2 as the intial value of the result. Key points:
 *
 * - All keys of obj2 are initially in the result.
 *
 * - If the loop finds a key (from obj1, remember) not in obj2, it adds
 *   it to the result.
 *
 * - If the loop finds a key that are both in obj1 and obj2, it compares
 *   the value. If it's the same value, the key is removed from the result.
 */
function getObjectDiff(obj1, obj2) {
    const diff = Object.keys(obj1).reduce((result, key) => {
        if (!obj2.hasOwnProperty(key)) {
            result.push(key);
        } else if (_.isEqual(obj1[key], obj2[key])) {
            const resultKeyIndex = result.indexOf(key);
            result.splice(resultKeyIndex, 1);
        }
        return result;
    }, Object.keys(obj2));

    return diff;
}

Đây là một ví dụ đầu ra:

// Test
let obj1 = {
    a: 1,
    b: 2,
    c: { foo: 1, bar: 2},
    d: { baz: 1, bat: 2 }
}

let obj2 = {
    b: 2, 
    c: { foo: 1, bar: 'monkey'}, 
    d: { baz: 1, bat: 2 }
    e: 1
}
getObjectDiff(obj1, obj2)
// ["c", "e", "a"]

Nếu bạn không quan tâm đến các đối tượng lồng nhau và muốn bỏ qua lodash, bạn có thể thay thế _.isEqualđể so sánh giá trị bình thường, ví dụ obj1[key] === obj2[key].


Câu trả lời được chọn này là chính xác cho chỉ kiểm tra sự bình đẳng. Nếu bạn cần biết sự khác biệt là gì, không có cách rõ ràng nào để liệt kê chúng, nhưng câu trả lời này khá hay, chỉ cần đưa ra một danh sách các khóa thuộc tính cấp cao nhất có sự khác biệt. (Và nó đưa ra câu trả lời là một hàm, làm cho nó có thể sử dụng được.)
Sigfried

Sự khác biệt giữa làm điều này và chỉ sử dụng _.isEqual (obj1, obj2) là gì? Việc thêm kiểm tra hasOwnProperty làm gì mà _.isEqual không làm được? Tôi đã giả định rằng nếu obj1 có một tài sản mà obj2 không có, _.isEqual sẽ không trả về đúng không ..?
Jaked 222

2
@ Jaked222 - sự khác biệt là isEqual trả về một boolean cho bạn biết các đối tượng có bằng nhau hay không, trong khi hàm trên cho bạn biết có khác nhau giữa hai đối tượng (nếu chúng khác nhau). Nếu bạn chỉ muốn biết liệu hai đối tượng có giống nhau không, isEqual là khá đủ. Trong nhiều trường hợp, bạn muốn biết sự khác biệt giữa hai đối tượng. Một ví dụ có thể là nếu bạn muốn phát hiện các thay đổi trước và sau một cái gì đó và sau đó gửi một sự kiện dựa trên các thay đổi.
Johan Persson

30

Dựa trên câu trả lời của Adam Boduch , tôi đã viết hàm này để so sánh hai đối tượng theo nghĩa sâu nhất có thể , trả về các đường dẫn có các giá trị khác nhau cũng như các đường dẫn bị thiếu từ một hoặc đối tượng khác.

Mã không được viết với hiệu quả trong tâm trí và các cải tiến về vấn đề đó được hoan nghênh nhất, nhưng đây là hình thức cơ bản:

var compare = function (a, b) {

  var result = {
    different: [],
    missing_from_first: [],
    missing_from_second: []
  };

  _.reduce(a, function (result, value, key) {
    if (b.hasOwnProperty(key)) {
      if (_.isEqual(value, b[key])) {
        return result;
      } else {
        if (typeof (a[key]) != typeof ({}) || typeof (b[key]) != typeof ({})) {
          //dead end.
          result.different.push(key);
          return result;
        } else {
          var deeper = compare(a[key], b[key]);
          result.different = result.different.concat(_.map(deeper.different, (sub_path) => {
            return key + "." + sub_path;
          }));

          result.missing_from_second = result.missing_from_second.concat(_.map(deeper.missing_from_second, (sub_path) => {
            return key + "." + sub_path;
          }));

          result.missing_from_first = result.missing_from_first.concat(_.map(deeper.missing_from_first, (sub_path) => {
            return key + "." + sub_path;
          }));
          return result;
        }
      }
    } else {
      result.missing_from_second.push(key);
      return result;
    }
  }, result);

  _.reduce(b, function (result, value, key) {
    if (a.hasOwnProperty(key)) {
      return result;
    } else {
      result.missing_from_first.push(key);
      return result;
    }
  }, result);

  return result;
}

Bạn có thể thử mã bằng đoạn mã này (nên chạy ở chế độ toàn trang):


4
Tôi chỉ sửa lỗi, nhưng để cho bạn biết, bạn nên kiểm tra sự tồn tại của khóa trong một đối tượng b bằng cách sử dụng b.hasOwnProperty(key)hoặckey in b không b[key] != undefined. Với phiên bản cũ đã sử dụng b[key] != undefined, hàm trả về một khác biệt không chính xác cho các đối tượng có chứa undefined, như trong compare({disabled: undefined}, {disabled: undefined}). Trên thực tế, phiên bản cũ cũng có vấn đề với null; bạn có thể tránh các vấn đề như vậy bằng cách luôn luôn sử dụng ===!== thay vì ==!=.
Rory O'Kane

23

Đây là một giải pháp ngắn gọn:

_.differenceWith(a, b, _.isEqual);

7
Dường như không làm việc với các đối tượng cho tôi. Thay vào đó trả về một mảng trống.
tomhughes

2
Cũng nhận được mảng trống với Lodash 4.17.4
aristidesfl

@ Z.Khullah Nếu nó hoạt động theo cách này, nó không được ghi lại.
Brendon

1
@Brendon, @THughes, @aristidesfl xin lỗi, tôi đã trộn lẫn nhiều thứ, nó hoạt động với các mảng của các đối tượng, nhưng không phải để so sánh đối tượng sâu. Hóa ra, nếu không có tham số nào là mảng, lodash sẽ chỉ trả về [].
Z. Khullah

7

Để hiển thị đệ quy một đối tượng khác với đối tượng khác như thế nào, bạn có thể sử dụng _.reduce kết hợp với _.isEqual_.isPlainObject . Trong trường hợp này, bạn có thể so sánh cách a khác với b hoặc cách b khác với a:

var a = {prop1: {prop1_1: 'text 1', prop1_2: 'text 2', prop1_3: [1, 2, 3]}, prop2: 2, prop3: 3};
var b = {prop1: {prop1_1: 'text 1', prop1_3: [1, 2]}, prop2: 2, prop3: 4};

var diff = function(obj1, obj2) {
  return _.reduce(obj1, function(result, value, key) {
    if (_.isPlainObject(value)) {
      result[key] = diff(value, obj2[key]);
    } else if (!_.isEqual(value, obj2[key])) {
      result[key] = value;
    }
    return result;
  }, {});
};

var res1 = diff(a, b);
var res2 = diff(b, a);
console.log(res1);
console.log(res2);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>


7

_.isEqualPhương pháp sử dụng đơn giản , nó sẽ hoạt động cho tất cả so sánh ...

  • Lưu ý: Phương pháp này hỗ trợ so sánh mảng, bộ đệm mảng, booleans, * đối tượng ngày, đối tượng lỗi, bản đồ, số, Objectđối tượng, biểu thức chính quy, * bộ, chuỗi, ký hiệu và mảng được nhập. Objectcác đối tượng được so sánh * bởi các thuộc tính riêng của chúng, không được kế thừa. Các hàm và nút DOM * không được hỗ trợ.

Vì vậy, nếu bạn có dưới đây:

 const firstName = {name: "Alireza"};
 const otherName = {name: "Alireza"};

Nếu bạn làm: _.isEqual(firstName, otherName);,

nó sẽ trở lại đúng

Và nếu const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};

Nếu bạn làm: _.isEqual(firstName, fullName);,

sẽ trả lại sai


6

Mã này trả về một đối tượng với tất cả các thuộc tính có giá trị khác nhau và cả giá trị của cả hai đối tượng. Hữu ích để đăng nhập sự khác biệt.

var allkeys = _.union(_.keys(obj1), _.keys(obj2));
var difference = _.reduce(allkeys, function (result, key) {
  if ( !_.isEqual(obj1[key], obj2[key]) ) {
    result[key] = {obj1: obj1[key], obj2: obj2[key]}
  }
  return result;
}, {});

3

Không sử dụng lodash / gạch dưới, tôi đã viết mã này và đang làm việc tốt với tôi để so sánh sâu sắc đối tượng1 với object2

function getObjectDiff(a, b) {
    var diffObj = {};
    if (Array.isArray(a)) {
        a.forEach(function(elem, index) {
            if (!Array.isArray(diffObj)) {
                diffObj = [];
            }
            diffObj[index] = getObjectDiff(elem, (b || [])[index]);
        });
    } else if (a != null && typeof a == 'object') {
        Object.keys(a).forEach(function(key) {
            if (Array.isArray(a[key])) {
                var arr = getObjectDiff(a[key], b[key]);
                if (!Array.isArray(arr)) {
                    arr = [];
                }
                arr.forEach(function(elem, index) {
                    if (!Array.isArray(diffObj[key])) {
                        diffObj[key] = [];
                    }
                    diffObj[key][index] = elem;
                });
            } else if (typeof a[key] == 'object') {
                diffObj[key] = getObjectDiff(a[key], b[key]);
            } else if (a[key] != (b || {})[key]) {
                diffObj[key] = a[key];
            } else if (a[key] == (b || {})[key]) {
                delete a[key];
            }
        });
    }
    Object.keys(diffObj).forEach(function(key) {
        if (typeof diffObj[key] == 'object' && JSON.stringify(diffObj[key]) == '{}') {
            delete diffObj[key];
        }
    });
    return diffObj;
}

3

So sánh sâu bằng cách sử dụng một mẫu các thuộc tính (lồng nhau) để kiểm tra

function objetcsDeepEqualByTemplate(objectA, objectB, comparisonTemplate) {
  if (!objectA || !objectB) return false

  let areDifferent = false
  Object.keys(comparisonTemplate).some((key) => {
    if (typeof comparisonTemplate[key] === 'object') {
      areDifferent = !objetcsDeepEqualByTemplate(objectA[key], objectB[key], comparisonTemplate[key])
      return areDifferent
    } else if (comparisonTemplate[key] === true) {
      areDifferent = objectA[key] !== objectB[key]
      return areDifferent
    } else {
      return false
    }
  })

  return !areDifferent
}

const objA = { 
  a: 1,
  b: {
    a: 21,
    b: 22,
  },
  c: 3,
}

const objB = { 
  a: 1,
  b: {
    a: 21,
    b: 25,
  },
  c: true,
}

// template tells which props to compare
const comparisonTemplateA = {
  a: true,
  b: {
    a: true
  }
}
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateA)
// returns true

const comparisonTemplateB = {
  a: true,
  c: true
}
// returns false
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateB)

Điều này sẽ làm việc trong giao diện điều khiển. Hỗ trợ mảng có thể được thêm vào nếu cần


2

Tôi đã lấy mã của Adam Boduch để tạo ra một sự khác biệt sâu sắc - điều này hoàn toàn chưa được kiểm tra nhưng các mảnh ở đó:

function diff (obj1, obj2, path) {
    obj1 = obj1 || {};
    obj2 = obj2 || {};

    return _.reduce(obj1, function(result, value, key) {
        var p = path ? path + '.' + key : key;
        if (_.isObject(value)) {
            var d = diff(value, obj2[key], p);
            return d.length ? result.concat(d) : result;
        }
        return _.isEqual(value, obj2[key]) ? result : result.concat(p);
    }, []);
}

diff({ foo: 'lol', bar: { baz: true }}, {}) // returns ["foo", "bar.baz"]

1
Hoạt động như một bùa mê, chỉ là thứ tự của obj1 và obj2 là quan trọng. Ví dụ: diff({}, { foo: 'lol', bar: { baz: true }}) // returns []
amangpt777

2

Như đã hỏi, đây là một hàm so sánh đệ quy. Và một chút nữa. Giả sử rằng việc sử dụng chính của chức năng đó là kiểm tra đối tượng, tôi có vài điều muốn nói. Hoàn toàn so sánh sâu là một ý tưởng tồi khi một số khác biệt là không liên quan. Ví dụ, so sánh sâu mù quáng trong các xác nhận TDD làm cho các xét nghiệm trở nên giòn không cần thiết. Vì lý do đó, tôi muốn giới thiệu một phần khác biệt có giá trị hơn nhiều . Nó là một tương tự đệ quy của một đóng góp trước đó cho chủ đề này. Nó bỏ qua các phím không có mặt trong một

var bdiff = (a, b) =>
    _.reduce(a, (res, val, key) =>
        res.concat((_.isPlainObject(val) || _.isArray(val)) && b
            ? bdiff(val, b[key]).map(x => key + '.' + x) 
            : (!b || val != b[key] ? [key] : [])),
        []);

BDiff cho phép kiểm tra các giá trị dự kiến ​​trong khi dung sai các thuộc tính khác, đó chính xác là những gì bạn muốn để kiểm tra tự động . Điều này cho phép xây dựng tất cả các loại xác nhận nâng cao. Ví dụ:

var diff = bdiff(expected, actual);
// all expected properties match
console.assert(diff.length == 0, "Objects differ", diff, expected, actual);
// controlled inequality
console.assert(diff.length < 3, "Too many differences", diff, expected, actual);

Trở lại với giải pháp hoàn chỉnh. Xây dựng một khác biệt truyền thống đầy đủ với bdiff là tầm thường:

function diff(a, b) {
    var u = bdiff(a, b), v = bdiff(b, a);
    return u.filter(x=>!v.includes(x)).map(x=>' < ' + x)
    .concat(u.filter(x=>v.includes(x)).map(x=>' | ' + x))
    .concat(v.filter(x=>!u.includes(x)).map(x=>' > ' + x));
};

Chạy chức năng trên trên hai đối tượng phức tạp sẽ tạo ra một cái gì đó tương tự như sau:

 [
  " < components.0.components.1.components.1.isNew",
  " < components.0.cryptoKey",
  " | components.0.components.2.components.2.components.2.FFT.min",
  " | components.0.components.2.components.2.components.2.FFT.max",
  " > components.0.components.1.components.1.merkleTree",
  " > components.0.components.2.components.2.components.2.merkleTree",
  " > components.0.components.3.FFTResult"
 ]

Cuối cùng, để có cái nhìn tổng quát về các giá trị khác nhau như thế nào, chúng ta có thể muốn trực tiếp eval () đầu ra khác. Vì thế, chúng ta cần một phiên bản bdiff xấu hơn tạo ra các đường dẫn chính xác về mặt cú pháp:

// provides syntactically correct output
var bdiff = (a, b) =>
    _.reduce(a, (res, val, key) =>
        res.concat((_.isPlainObject(val) || _.isArray(val)) && b
            ? bdiff(val, b[key]).map(x => 
                key + (key.trim ? '':']') + (x.search(/^\d/)? '.':'[') + x)
            : (!b || val != b[key] ? [key + (key.trim ? '':']')] : [])),
        []);

// now we can eval output of the diff fuction that we left unchanged
diff(a, b).filter(x=>x[1] == '|').map(x=>[x].concat([a, b].map(y=>((z) =>eval('z.' + x.substr(3))).call(this, y)))));

Điều đó sẽ tạo ra một cái gì đó tương tự như thế này:

[" | components[0].components[2].components[2].components[2].FFT.min", 0, 3]
[" | components[0].components[2].components[2].components[2].FFT.max", 100, 50]

Giấy phép MIT;)


1

Hoàn thành câu trả lời từ Adam Boduch, điều này có sự khác biệt về tài sản

const differenceOfKeys = (...objects) =>
  _.difference(...objects.map(obj => Object.keys(obj)));
const differenceObj = (a, b) => 
  _.reduce(a, (result, value, key) => (
    _.isEqual(value, b[key]) ? result : [...result, key]
  ), differenceOfKeys(b, a));

1

Nếu bạn chỉ cần so sánh chính:

 _.reduce(a, function(result, value, key) {
     return b[key] === undefined ? key : []
  }, []);

0

Dưới đây là một Bản mô tả đơn giản với trình kiểm tra chênh lệch sâu Lodash sẽ tạo ra một đối tượng mới chỉ với sự khác biệt giữa một đối tượng cũ và một đối tượng mới.

Ví dụ: nếu chúng ta có:

const oldData = {a: 1, b: 2};
const newData = {a: 1, b: 3};

đối tượng kết quả sẽ là:

const result: {b: 3};

Nó cũng tương thích với các đối tượng sâu đa cấp, đối với các mảng, nó có thể cần một số điều chỉnh.

import * as _ from "lodash";

export const objectDeepDiff = (data: object | any, oldData: object | any) => {
  const record: any = {};
  Object.keys(data).forEach((key: string) => {
    // Checks that isn't an object and isn't equal
    if (!(typeof data[key] === "object" && _.isEqual(data[key], oldData[key]))) {
      record[key] = data[key];
    }
    // If is an object, and the object isn't equal
    if ((typeof data[key] === "object" && !_.isEqual(data[key], oldData[key]))) {
      record[key] = objectDeepDiff(data[key], oldData[key]);
    }
  });
  return record;
};

-1
var isEqual = function(f,s) {
  if (f === s) return true;

  if (Array.isArray(f)&&Array.isArray(s)) {
    return isEqual(f.sort(), s.sort());
  }
  if (_.isObject(f)) {
    return isEqual(f, s);
  }
  return _.isEqual(f, s);
};

Điều này không hợp lệ. Bạn không thể so sánh ===trực tiếp với các đối tượng , { a: 20 } === { a: 20 }sẽ trả về false, vì nó so sánh nguyên mẫu. Cách đúng đắn hơn để chủ yếu so sánh các đối tượng là bọc chúng vàoJSON.stringify()
Herrgott

if (f === s) trả về true; - chỉ dành cho đệ quy. Có a: 20} === {a: 20} sẽ trả về false và chuyển sang điều kiện tiếp theo
Crusader

Tại sao không chỉ _.isEqual(f, s)? :)
Herrgott

Điều này sẽ dẫn đến một vòng lặp đệ quy vô hạn bởi vì nếu flà một đối tượng và bạn nhận được if (_.isObject(f))bạn chỉ cần quay lại hàm và nhấn lại điểm đó. Tương tự như vậy đối vớif (Array.isArray(f)&&Array.isArray(s))
rady

-2

điều này được dựa trên @JLavoie , sử dụng lodash

let differences = function (newObj, oldObj) {
      return _.reduce(newObj, function (result, value, key) {
        if (!_.isEqual(value, oldObj[key])) {
          if (_.isArray(value)) {
            result[key] = []
            _.forEach(value, function (innerObjFrom1, index) {
              if (_.isNil(oldObj[key][index])) {
                result[key].push(innerObjFrom1)
              } else {
                let changes = differences(innerObjFrom1, oldObj[key][index])
                if (!_.isEmpty(changes)) {
                  result[key].push(changes)
                }
              }
            })
          } else if (_.isObject(value)) {
            result[key] = differences(value, oldObj[key])
          } else {
            result[key] = value
          }
        }
        return result
      }, {})
    }

https://jsfiddle.net/EmilianoBarboza/0g0sn3b9/8/


-2

chỉ sử dụng vanilla js

let a = {};
let b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

JSON.stringify(a) === JSON.stringify(b);
// false
b.prop2 = { prop3: 2};

JSON.stringify(a) === JSON.stringify(b);
// true

nhập mô tả hình ảnh ở đây


1
Phương pháp này sẽ không cho bạn biết thuộc tính nào khác nhau.
JLavoie

2
Trong trường hợp này, ảnh hưởng thứ tự thuộc tính trong kết quả.
Victor Oliveira

-2

Để xây dựng theo câu trả lời của Sridhar Gudimela , ở đây, nó được cập nhật theo cách sẽ khiến Flow hài lòng:

"use strict"; /* @flow */



//  E X P O R T

export const objectCompare = (objectA: any, objectB: any) => {
  let diffObj = {};

  switch(true) {
    case (Array.isArray(objectA)):
      objectA.forEach((elem, index) => {
        if (!Array.isArray(diffObj))
          diffObj = [];

        diffObj[index] = objectCompare(elem, (objectB || [])[index]);
      });

      break;

    case (objectA !== null && typeof objectA === "object"):
      Object.keys(objectA).forEach((key: any) => {
        if (Array.isArray(objectA[key])) {
          let arr = objectCompare(objectA[key], objectB[key]);

          if (!Array.isArray(arr))
            arr = [];

          arr.forEach((elem, index) => {
            if (!Array.isArray(diffObj[key]))
              diffObj[key] = [];

            diffObj[key][index] = elem;
          });
        } else if (typeof objectA[key] === "object")
          diffObj[key] = objectCompare(objectA[key], objectB[key]);
        else if (objectA[key] !== (objectB || {})[key])
          diffObj[key] = objectA[key];
        else if (objectA[key] === (objectB || {})[key])
          delete objectA[key];
      });

      break;

    default:
      break;
  }

  Object.keys(diffObj).forEach((key: any) => {
    if (typeof diffObj[key] === "object" && JSON.stringify(diffObj[key]) === "{}")
      delete diffObj[key];
  });

  return diffObj;
};
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.