문제 상황
다음과 같이 여러 단계로 중첩된 JSON 객체가 있다고 가정해 보겠습니다.
const obj = {
a: {
someKey: {
propOne: '',
enabled: true
}
},
b: {
someKey: {
propOne: '',
enabled: false
}
},
c: {
someKey: {
propOne: '',
enabled: false
}
},
someKey: {
ab: {
propOne: '',
enabled: true
}
}
};이제 요구 사항은 하나의 JavaScript 함수를 작성하여, 이런 객체를 입력으로 받으면 enabled 속성 값이 falsy인 모든 키를 재귀적으로 탐색하면서 원본 객체에서 직접(in-place) 제거하는 것입니다.
해결 방법
Object.keys()로 객체의 모든 키를 가져온 뒤 forEach()로 순회하고, 값이 객체라면 자기 자신을 다시 호출하는 재귀 방식으로 문제를 해결할 수 있습니다. 핵심 로직은 다음과 같습니다.
- 현재 키의
enabled값이false이면 해당 키를 삭제합니다. - 현재 값이 객체라면 재귀적으로 함수를 호출해 내부도 검사합니다.
- 재귀 처리 후 하위 객체가 비어 있게 되면 그 빈 객체도 함께 삭제합니다.
코드 예제
const obj = {
a: {
someKey: {
propOne: '',
enabled: true
}
},
b: {
someKey: {
propOne: '',
enabled: false
}
},
c: {
someKey: {
propOne: '',
enabled: false
}
},
someKey: {
ab: {
propOne: '',
enabled: true
}
}
};
const deleteFalsyKey = obj => {
const keys = Object.keys(obj);
keys.forEach(key => {
if(obj[key].enabled === false){
delete obj[key];
return;
};
if(obj[key] && typeof obj[key] === 'object'){
deleteFalsyKey(obj[key]);
if (!Object.keys(obj[key]).length) {
delete obj[key];
};
}
});
};
deleteFalsyKey(obj);
console.log(obj);실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
{
a: { someKey: { propOne: '', enabled: true } },
someKey: { ab: { propOne: '', enabled: true } }
}결과를 보면 enabled: false였던 b와 c 키가 완전히 제거된 것을 확인할 수 있습니다. 이처럼 재귀 함수와 delete 연산자를 조합하면 깊이가 얼마든지 중첩된 객체에서도 조건에 맞는 속성을 간단하게 정리할 수 있습니다.