두 입력 값 비교 코드

두 개의 입력이 있을 때 이 입력의 값이 같은지 알고싶을 때 보통은 ===을 사용합니다. 

 

하지만 값이 원시값이 아니라면 객체, 배열, Map, Set이라면 우리가 봤을때는 같은 값이더라도 저장된 위치(주소)가 달라 같지 않다는 결과를 받을 수 있습니다. 

 

따라서 우리가 원하는 결과를 얻기 위해선 객체, 배열, Map, Set은 각각 값을 비교해줘야 합니다. 이를 비교할 때마다 하나하나 비교하는 코드를 작성하기엔 비효율적이기 때문에, 함수를 하나 만들어보았습니다. 

코드

function areEqual(value1, value2) {
  // 먼저 두 값이 동일한지 확인합니다.
  if (value1 === value2) return true;

  // 타입이 다르면 무조건 다릅니다.
  if (typeof value1 !== typeof value2 || value1 === null || value2 === null) return false;

  // Set 타입의 비교
  if (value1 instanceof Set && value2 instanceof Set) {
    if (value1.size !== value2.size) return false;
    for (let item of value1) {
      let found = false;
      for (let otherItem of value2) {
        if (areEqual(item, otherItem)) {
          found = true;
          break;
        }
      }
      if (!found) return false;
    }
    return true;
  }

  // Map 타입의 비교
  if (value1 instanceof Map && value2 instanceof Map) {
    if (value1.size !== value2.size) return false;
    for (let [key, value] of value1) {
      if (!value2.has(key)) return false;
      if (!areEqual(value, value2.get(key))) return false;
    }
    return true;
  }

  // 배열 타입의 비교
  if (Array.isArray(value1) && Array.isArray(value2)) {
    if (value1.length !== value2.length) return false;
    for (let i = 0; i < value1.length; i++) {
      if (!areEqual(value1[i], value2[i])) return false;
    }
    return true;
  }

  // 객체 타입의 비교
  if (typeof value1 === 'object' && typeof value2 === 'object') {
    const keys1 = Object.keys(value1);
    const keys2 = Object.keys(value2);
    if (keys1.length !== keys2.length) return false;
    for (let key of keys1) {
      if (!keys2.includes(key) || !areEqual(value1[key], value2[key])) return false;
    }
    return true;
  }

  // 기본적으로 다른 타입은 false를 반환합니다.
  return false;
}

여기서 주의해야 할 점은 객체, 배열, Map, Set 모두 값을 객체, 배열, Map, Set를 가질 수 있기 때문에 재귀로 areEqual로 확인이 가능한 위치까지 진행하는 방식입니다. 

 

사용법

areEqual(1,1); //true;
areEqual(new Set([{ a: 1 }, { b: 2 }]), new Set([{ a: 1 }, { b: 3 }]); // false
areEqual(new Map([['key1', { a: 1 }], ['key2', { b: 2 }]]), new Map([['key1', { a: 1 }], ['key2', { b: 2 }]])); //true