[LeetCode] 2727. Is Object Empty

1ilsang
1ilsang
클라이밍 하실래염?
published

cover

문제 링크

객체 혹은 배열이 비어있는지 확인하는 문제이다.

/**
 * @param {Object | Array} obj
 * @return {boolean}
 */
const isEmpty = (obj) => {
  return Object.keys(obj).length === 0;
};

배열 혹은 객체의 키가 있는지 확인하면 되므로 Object.keys의 길이가 0인지 확인하면 된다.

만약 keys로 추출 후 비교하는 것이 싫다면 아래와 같은 방법도 있다.

const isEmpty = (obj) => {
  for (i in obj) {
    return false;
  }
  return true;
};

배열 또한 객체이므로 for...in을 통해 속성 키값을 순회할 수 있는지 확인하면 된다.

keys로 모든 키값을 가져와 비교하는 것보다 순회와 동시에 객체가 비어있는지 판단이 가능하므로 훨씬 빠르다.

참고로 이 문제는 "상속된" 프로퍼티를 비교해야 하는지에 대한 명시가 없어 모호한 부분이 있다.

만약 상속된 프로퍼티까지 비교한다면 keysfor-in의 정답 여부가 달라졌을 것이다. 이 부분은 아래에서 다루겠다.

++ for-infor-of의 차이가 무엇일까?

for...in

for...in문은 상속된 열거 가능한 속성들을 포함하여 객체에서 문자열로 키가 지정된 모든 열거 가능한 속성에 대해 반복합니다(Symbol로 키가 지정된 속성은 무시합니다.).

MDN for...in 설명에 따르면 for...in은 상속된 모든 속성(Property)을 포함한 속성 키 값을 반복한다.

for..of

for...of 명령문은 반복가능한 객체 (Array, Map, Set, String, TypedArray, arguments 객체 등을 포함)에 대해서 반복하고 각 개별 속성값에 대해 실행되는 문이 있는 사용자 정의 반복 후크를 호출하는 루프를 생성합니다.

MDN for...of 설명에 따르면 for...of는 반복 가능한 객체의 속성 값에 대한 순회를 한다.

결론

Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  console.log(i); // "0", "1", "2", "foo", "arrCustom", "objCustom"
}
for (let i of iterable) {
  console.log(i); // 3, 5, 7
}
console.log(Object.keys(iterable)); // [ "0", "1", "2", "foo" ]

// Map 객체
const m = new Map([
  ['a', 1],
  ['b', 2],
]);
console.log(m); // Map(2) {'a' => 1, 'b' => 2}
for (let i in m) {
  console.log(i); // 순회 되지 않음. undefined
}
for (let i of m) {
  console.log(i); // ['a', 1], ['b', 2]
}
console.log(Object.keys(m)); // []

for...in 루프는 객체의 모든 열거 가능한 속성에 대해 반복하며 문자열 키 값을 반환한다. 추가로 인덱스의 순서를 보장하지 않는다.

for...of 구문은 컬렉션 전용이다. 모든 객체보다는, [Symbol.iterator] 속성이 있는 모든 컬렉션 요소에 대해 반복하며 컬렉션을 반환한다.

keys는 해당 키를 가져오지만, 상속된 값은 가져오지 않는다.