JavaScript에서 객체를 비교하려고 한다면 몇가지 주의해야 할 점이 있다.
다른 변수들과 달리 객체는 참조 타입이기 때문에 값이 아닌 메모리 주소를 비교한다. 따라서 두 개의 객체를 단순히 == 또는 === 연산자로 비교하면 엉뚱한 값이 나올 수 있다. 아래 예시를 살펴보자
1. 문제점
1. 참조비교
아래 예시를 보면 두 객체가 동일한 속성을 가지고 있지만 다른 메모리 주소를 가리키고 있기때문에 비교 결과가 false가 나온다.
const obj1 = { name: 'Kim' };
const obj2 = { name: 'Kim' };
console.log(obj1 == obj2); // false
console.log(obj1 === obj2); // false
// obj1과 obj2는 동일한 속성을 가지고 있지만, 각각 다른 객체로 다른 참조값을 가지고 있기때문에 결과가 false로 나온다
2. 얕은 비교
또한 객체를 == 또는 === 연산자로 비교하면 객체의 내부 속성까지 재귀적으로 비교하지 않기때문에 비교 결과가 다르게 나온다. 객체를 비교할 때는 내부까지 깊게 비교하여야한다.
const obj1 = { name: 'Kim', age: 20 };
const obj2 = { name: 'Kim', age: 20 };
console.log(obj1 == obj2); // false
console.log(obj1 === obj2); // false
console.log(obj1.name === obj2.name && obj1.age === obj2.age); // true
// 위의 예제에서 obj1과 obj2는 객체 전체를 비교하면 false가 나오지만 개별 속성을 비교하면 true가 나온다
따라서, 객체를 비교할 때는 객체의 속성을 비교하는 방법을 사용해야 한다.
2. 해결방법
deepEqual(obj1, obj2) {
// 두 객체의 타입을 비교
if (typeof obj1 !== typeof obj2) {
return false;
}
// 객체의 타입이 'object'인 경우 개별 속성을 비교
if (typeof obj1 === 'object' && obj1 !== null && obj2 !== null) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
// 속성 개수가 다른 경우 false를 반환
if (keys1.length !== keys2.length) {
return false;
}
// 속성의 값들을 재귀적으로 비교
for (let key of keys1) {
if (!deepEqual(obj1[key], obj2[key])) {
return false;
}
}
return true;
}
// 타입이 'object'가 아닌경우엔 단순히 값 비교를 수행
return obj1 === obj2;
}
이 외에도 Lodash나 Ramda와 같은 라이브러리를 사용하면 객체를 깊은 수준까지 비교하는 함수를 제공받을 수 있다.
'지금, 개발하기 > Javascript' 카테고리의 다른 글
javascript] 옵셔널체이닝(optional Chaining)이란? (0) | 2023.08.18 |
---|---|
javascript] 자바스크립트의 클래스 (0) | 2023.08.14 |
javascript] this 바인딩 파헤치기 (0) | 2023.01.13 |
javascript] 함수의 인자, Rest Parameter, Spread (0) | 2023.01.04 |
javascript] for문의 break vs continue, while vs do while (0) | 2022.12.16 |