var nodes = document.querySelectorAll('div'); // NodeList [div, div, div, div, div, ...]
var els = document.body.children; // HTMLCollection [noscript, link, div, script, ...]
위 유사배열을 Array.isArray 메서드(배열인지를 판단해주는 메서드)를 사용해서 배열인지 확인해 보면 아래와 같은 결과를 얻을 수 있습니다.
Array.isArray(nodes); // false
Array.isArray(els); // false
직접 배열 리터럴로 선언한 array(var array = [1, 2, 3])만 배열입니다. 비슷한 방법으로, array instanceof Array로도 판단할 수 있습니다.
nodes나 els처럼 [ ]로 감싸져있지만 배열이 아닌 친구들을 유사배열이라고 부릅니다.
배열과 유사배열을 구분해야 하는 이유는, 유사배열의 경우 배열의 메서드를 쓸 수 없기 때문입니다.
array.forEach(function(el) { console.log(el); }); // 1, 2, 3
els.forEach(function(el) { console.log(el); }); // Uncaught TypeError: els.forEach is not a function
els에 forEach같은 배열 메서드를 사용하면 에러가 발생합니다. (nodes는 프로토타입에 forEach가 있어서 됩니다.) 배열이 아니므로 발생하는 것입니다. 이럴 때 메서드를 빌려 쓰는 방법이 있습니다. 배열 프로토타입에서 forEach 메서드를 빌려오는 것이죠. 바로 call이나 apply입니다. 이 강좌에서 설명했습니다.
Array.prototype.forEach.call(nodes, function(el) { console.log(el); });
[].forEach.call(els, function(el) { console.log(el); });
이제 유사배열에도 forEach를 사용할 수 있습니다. map이나 filter, reduce 등의 다른 배열 메서드도 사용 가능합니다.
최신 자바스크립트에서는 Array.from으로 더 간단하게 할 수 있습니다.
Array.from(nodes).forEach(function(el) { console.log(el) });
자주 보는(ES6에서는 더 이상 안 보이지만) 유사배열이 하나 더 있습니다. function의 arguments입니다. 함수선언문에 넣은 인자 목록을 표시하죠.
function arrayLike() {
console.log(arguments);
}
arrayLike(4, 5, 6); // Arguments [4, 5, 6, callee, Symbol]
역시 forEach같은 배열 메서드를 쓸 수 없으므로 문제가 됩니다. 위에서 설명한 방법을 적용해야 합니다.
function arrayLike() {
console.log(arguments);
[].forEach.call(arguments, function(el) { console.log(el) });
}
arrayLike(4, 5, 6);
유사배열, 별 거 아니죠? []로 감싸져 있다고 다 같은 배열이 아니라는 것과, Array.isArray로 판별하는 방법, 배열 프로토타입에서 메서드를 빌려쓰는 방법에 대해서 알아두시면 좋습니다! 유사배열과 자주 만나는 프론트엔드에서는 필수입니다!
출처
https://www.zerocho.com/category/JavaScript/post/5af6f9e707d77a001bb579d2