191022_TIL(유사배열에 배열 메소드 사용하기)

유사배열에 배열 메소드 사용하기

포트폴리오 프로젝트 코드를 리팩토링 하던 중 document.querySelectorAll 을 사용하여 NodeLIst 객체를 받아서 배열 메소드인 map을 사용해야 할 일이 생겨서 아래와 같이 코드를 짰다.

1
2
3
const imgList = document.querySelectorAll('img');

const imgAlt = imgList.map(({ alt }) => alt);

다음과 같은 에러가 발생하였다.

1
Uncaught TypeError: imgList.map is not a function

왜 이런 에러가 발생했는지 잠시 생각해보니

너무나도 당연한 것이었다.

NodeList는 배열이 아닌 유사 배열 객체이기 때문에 배열 메소드인 map을 사용할 수 없었던 것이다.

그렇다면 배열인지 유사배열인지 어떻게 알 수 있을까?

1
2
3
4
5
6
7
8
const array = ['a', 'b', 'c'];

const imgList = document.querySelectorAll('img');

console.log(Array.isArray(array)); // true
console.log(Array.isArray(imgList)); // false
console.log(typeof(array)); // object
console.log(typeof(imgList)); // object

typeof 메소드를 사용하면 배열과 유사배열 모두 object로 나오기 때문에 구별을 할 수 없다. 하지만

Array.isArray 메소드를 사용하면 배열일 때만 true를 return 해주기 때문에 쉽게 구별할 수 있다.

배열과 유사배열을 구분해야 하는 이유는 위에서 언급했다시피 유사배열에 map같은 배열 메소드를 사용하면 에러가 발생하기 때문이다.

하지만, 사실 유사배열에도 배열 메소드를 사용할 수 있는 방법이 있다. 내가 아는 방법은 총 3가지이다.

  1. Array객체의 프로토타입에서 해당 배열 메소드를 빌려서 사용하는 방법(call, apply)
1
2
Array.prototype.map.call(imgList, img => console.log(img));
[].map.call(imgList, img => console.log(img));
  1. Array.from() 메소드 사용

    Array.from() 메소드는 유사 배열 객체나 반복 가능한 객체(iterable object)를 얕게 복사하여 새로운 Array 객체를 만든다.

1
Array.from(imgList).forEach((img) => console.log(img));
  1. Spread 연산자를 사용하여 배열 안에서 풀어주는 방법
1
[...imgList].map(img => console.log(img));

참고 자료

MDN-Array.from

제로초-배열과 유사배열

Share