So sánh hai object trong JavaScript có thể là một nhiệm vụ phức tạp vì các object được so sánh theo tham chiếu, không phải theo giá trị. Điều này có nghĩa là nếu bạn sử dụng toán tử == hoặc ===, hai object sẽ chỉ được coi là bằng nhau nếu chúng tham chiếu đến cùng một đối tượng trong bộ nhớ.

Dưới đây là một số cách để so sánh hai object theo giá trị, tức là kiểm tra xem tất cả các thuộc tính và giá trị của chúng có giống nhau không.

1. So sánh Shallow (Nông)

Đây là cách so sánh cơ bản và nhanh chóng. Nó chỉ kiểm tra các thuộc tính trực tiếp của object mà không đi sâu vào các object con bên trong. Bạn có thể sử dụng cách tiếp cận này nếu bạn chỉ cần so sánh các thuộc tính primitive (số, chuỗi, boolean, v.v.).

Ví dụ:

function shallowEqual(obj1, obj2) {
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);

    // Kiểm tra nếu số lượng thuộc tính khác nhau
    if (keys1.length !== keys2.length) {
        return false;
    }

    // So sánh từng giá trị của thuộc tính
    for (let key of keys1) {
        if (obj1[key] !== obj2[key]) {
            return false;
        }
    }

    return true;
}

const objA = { a: 1, b: 2 };
const objB = { a: 1, b: 2 };
const objC = { a: 1, b: 3 };

console.log(shallowEqual(objA, objB)); // true
console.log(shallowEqual(objA, objC)); // false

2. So sánh Deep (Sâu)

So sánh deep đi sâu vào từng cấp độ của object, bao gồm cả các object con, để đảm bảo tất cả các thuộc tính và giá trị đều giống nhau.

Ví dụ:

function deepEqual(obj1, obj2) {
    if (obj1 === obj2) {
        return true; // Nếu là cùng một tham chiếu
    }

    if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
        return false; // Nếu một trong hai không phải là object hoặc là null
    }

    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);

    if (keys1.length !== keys2.length) {
        return false;
    }

    for (let key of keys1) {
        // Đệ quy để so sánh các thuộc tính con
        if (!deepEqual(obj1[key], obj2[key])) {
            return false;
        }
    }

    return true;
}

const objA = { a: 1, b: { c: 2 } };
const objB = { a: 1, b: { c: 2 } };
const objC = { a: 1, b: { c: 3 } };

console.log(deepEqual(objA, objB)); // true
console.log(deepEqual(objA, objC)); // false

3. Sử dụng JSON để so sánh (Shallow)

Một cách nhanh chóng để so sánh hai object (chỉ cho object không chứa hàm hoặc thuộc tính phức tạp như undefined hoặc Symbol) là chuyển đổi chúng thành chuỗi JSON và so sánh:

const objA = { a: 1, b: 2 };
const objB = { a: 1, b: 2 };

console.log(JSON.stringify(objA) === JSON.stringify(objB)); // true

4. Sử dụng thư viện Lodash

Nếu bạn đang tìm kiếm một cách tiếp cận đơn giản hơn mà không phải tự viết hàm so sánh, thư viện Lodash cung cấp phương thức _.isEqual để so sánh sâu giữa hai object:

const _ = require('lodash');

const objA = { a: 1, b: { c: 2 } };
const objB = { a: 1, b: { c: 2 } };

console.log(_.isEqual(objA, objB)); // true

Tổng kết

  • Shallow comparison: So sánh các thuộc tính trực tiếp của object, phù hợp khi object chỉ chứa các giá trị primitive.
  • Deep comparison: So sánh toàn bộ các thuộc tính ở mọi cấp độ của object, bao gồm cả các object con.
  • JSON comparison: Nhanh chóng và tiện lợi, nhưng chỉ phù hợp với các object đơn giản không chứa hàm hoặc giá trị không phải là JSON.
  • Thư viện Lodash: Cung cấp một giải pháp tiện lợi và đã được kiểm chứng để so sánh sâu các object.