배열과 HTMLCollection / NodeList 객체
DOM 컬렉션 객체인 HTMLCollection 객체와 NodeList 객체는 DOM API가 여러 개의 값을 반환하기위한 객체입니다. 둘다 유사배열 객체이면서 이터러블이므로 for…of문을 포함한 여러 방법으로 순회가 가능합니다. 또한 스프레드 문법을 사용하여 배열로 간단히 변환할 수 있습니다.
HTMLCollection과 NodeList는 노드 객체의 상태를 실시간으로 반영하는 살아있는 객체라는 것입니다. HTMLCollection 객체는 언제나 ‘live 객체’로 동작하지만 NodeList 객체는 기본적으로 실시간으로 반영하지 않고 과거의 상태를 유지하지면 경우에 따라서는 live 객체로 동작합니다.
HTMLCollection 객체
HTMLCollection 객체는 getElementsByTagName, getElementByClassName 메서가 반환하는 노드 객체입니다. HTMLCollection 객체는 노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 DOM 컬렉션 객체로 ‘live 객체’라고 부르기도 합니다.
1 | <!DOCTYPE html> |
위 코드에서 class 값이 ‘red’인 요소를 모두 취득하고 for문을 통해 모든 요소의 class 값을 ‘blue’로 변경하였습니다. 우리가 생각할 때 모든 li 요소의 class 값이 ‘blue’로 변경될 것이라고 생각하지만 예상대로 동작하지 않습니다.
이것은 HTMLCollection 객체가 live 객체의 특성을 가지고 있기 때문입니다. for문을 돌면서 i === 0 에서 첫번째 li의 class의 값을 ‘blue’로 변경합니다. 이 때 $elements가 참조하는 컬렉션 객체는 실시간으로 상태를 반영하여 HTMLCollection(2)[li.red, li.red] 상태가 됩니다. 따라서 i === 1 에서 적용되는 대상은 첫 선언한 요소들 중 세번째 li가 됩니다. 따라서 HTMLCollection 객체를 반복문을 통해 순회할 때에는 주의가 필요합니다.
NodeList 객체
HTMLCollection 객체의 부작용을 회피하기 위해 NodeList 객체를 이용하는 방법이 있습니다. querySellectorAll 메서드를 사용하면 DOM 컬렉션 객체인 NodeList를 반환합니다. 이 때 NodeList는 실시간으로 상태를 반영하지 않는 non-live 객체입니다. 그러나 childNodes 프로퍼티가 반환하는 NodeList객체는 live 객체로 동작합니다.
안전하게 DOM 컬렉션 객체를 활용하는 방법
HTMLCollection의 경우 live 객체의 특성 때문에 개발자가 예상치 못한 결과를 초래할 수 있다는 위험성이 있고, NodeList의 경우는 대부분 non-live 객체로 동작하지만 일부 상황에선 live-객체로 동작하는 위험성이 있습니다. 따라서 Dom 컬렉션 객체를 직접적으로 참조하는 것보다 배열로 변환하여 활용하는 방법을 추천합니다. ES6의 스프레드 문법을 통해 간단히 배열로 변환할 수 있습니다. 배열로 변환하게 되면 배열의 프로토타입을 상속받아 여러 메서드들도 사용할 수 있습니다.
1 | const $elements = [...document.getElementsByClassName("red")]; |
forEach 메서드
HTMLCollection 객체는 forEach 메서드 사용이 불가능하고 NodeList 객체는 가능합니다. 보다 정확히 말하면 배열의 forEach 메서드는 배열만 사용이 가능하며 DOM 컬렉션 객체는 사용이 불가능합니다. 그 이유는 우리가 배열에서 사용하는 forEach 메서드가 Array.prototype의 프로퍼티를 상속받아 사용하고 있기 때문입니다. 따라서 비슷한 형태의 리스트 데이터지만 DOM 컬렉션 객체는 배열이 아니기 때문에 DOM을 조작하면서 기존의 배열의 문법들로 구현하는 것에는 한계가 있습니다.
NodeList는 forEach가 되는데요?
NodeList도 기존에는 forEach 메서드를 사용한 순회가 불가능 했습니다. 하지만 사용성을 위해 Web API에 추가된 기능입니다. 따라서 NodeList의 forEach 메서드는 배열의 forEach 메서드와 같은 동작을 하는 다른 메서드입니다.