Vanilla JavaScript에서 객체의 심층 평등 검사 👨‍👦

13501 단어 javascript
JavaScript를 사용하여 두 개체를 서로 비교해야 하는 상황에 처한 적이 있습니까? 아마도 JavaScript가 이 문제에 대한 기본 솔루션을 제공하지 않는다는 것을 알게 되었을 것입니다. 이 튜토리얼에서는 이를 위한 자체 구현을 구축할 것입니다!

다음에 대해 배우게 됩니다.
  • 값에 의한 전달 대 참조에 의한 전달
  • Object.keys() 메서드
  • 재귀 함수 만들기

  • Lodash 라이브러리를 가져오고 그들의 .isEqual 방법을 사용하여 두 개체의 심층 품질 검사를 수행할 수 있지만 바닐라 JavaScript를 실행하기 위해 직접 솔루션을 만드는 것이 좋습니다.

    다음과 같은 객체가 있다고 가정해 보겠습니다.

    const obj1 = { name: 'Peter', stats: { points: 45, isActive: false }};
    const obj2 = { name: 'Peter', stats: { points: 45, isActive: false }};
    
    console.log(obj1 === obj2) // returns false
    

    이 두 개체는 정확히 동일하지만 JavaScript는 여전히 false를 반환합니다. 왜요?

    문자열 및 숫자와 같은 JavaScript 프리미티브는 해당 값으로 비교되기 때문입니다. 반면 객체는 참조로 비교됩니다.

    JavaScript는 생성한 각 개체를 메모리의 자체 위치에 할당합니다. 따라서 객체의 내용이 정확히 동일하더라도 해당 참조(메모리 내 위치)는 다릅니다!



    함수 생성을 시작하겠습니다. 두 개의 인수를 받는 compareObjects라는 함수를 설정할 것입니다. 먼저 두 인수가 동일한 유형이고 동일한 값을 포함하는지 확인합니다.

    const compareObjects = (a, b) => a === b ? true : false;
    
    const obj1 = { name: 'Peter', stats: { points: 45, isActive: false }};
    
    compareObjects(obj1, obj1) // returns true
    

    다음으로 두 인수가 실제로 object 유형이고 또한 null 값이 아닌지 검사를 추가합니다. 유형 변환을 피하고 싶으므로 != 대신 !==를 사용합니다.

    const compareObjects = (a, b) => {
     if (a === b) return true;
    
     if (typeof a != 'object' || typeof b != 'object' || typeof a == null || typeof b == null) return false;
    }
    

    그런 다음 두 객체의 객체 키 길이를 확인합니다. 길이가 같지 않으면 물체가 같지 않다고 확신할 수 있습니다.

    ...
    let keysA = Object.keys(a), keysB = Object.keys(b);
     if (keysA.length != keysB.length) return false;
    ...
    

    다음으로 for of 루프를 사용하여 keysA 배열의 키를 반복합니다. 배열에는 for of를 사용하고 객체에는 for in를 사용하십시오.

    이 루프 내에서 모든 키가 keysB 배열 내에 존재하는지 확인합니다. 그 다음에는 compareObjects 함수에 다시 전달하여 모든 키의 값을 비교하여 함수를 재귀적으로 만듭니다(자체 호출).

    값의 키 중 하나가 같지 않으면 루프와 함수를 중지하고 false를 반환합니다.

    ...
    for (let key of keysA) {
        if (!keysB.includes(key) || !compareObjects(a[key], b[key])) return false;
    }
    ...
    
    

    또한 메소드가 동일한지 확인하고 싶습니다. 두 값을 비교하여 함수를 문자열로 변환하여 이를 수행합니다.

    ...
    if (typeof a[key] === 'function' || typeof b[key] === 'function') {
       if (a[key].toString() != b[key].toString()) return false;
    }
    ...
    

    루프가 모든 키를 확인하고 중첩된 모든 값을 자체 함수로 다시 전달했지만 false를 반환하지 않은 경우 남은 작업은 true를 반환하는 것뿐입니다!

    완전한 기능:

    const compareObjects = (a, b) => {
     if (a === b) return true;
    
     if (typeof a != 'object' || typeof b != 'object' || a == null || b == null) return false;
    
     let keysA = Object.keys(a), keysB = Object.keys(b);
    
     if (keysA.length != keysB.length) return false;
    
     for (let key of keysA) {
       if (!keysB.includes(key)) return false;
    
       if (typeof a[key] === 'function' || typeof b[key] === 'function') {
         if (a[key].toString() != b[key].toString()) return false;
       } else {
         if (!compareObjects(a[key], b[key])) return false;
       }
     }
    
     return true;
    }
    

    이 튜토리얼을 따라 주셔서 감사합니다. 더 많은 내용을 보려면 저를 팔로우하세요! 🧠

    자세한 내용은 Eloquent JavaScript 책을 참조하십시오.

    좋은 웹페이지 즐겨찾기