Overview
Lists of elements obtained with document.querySelectorAll (NodeList), the arguments object in functions, and strings can be accessed by index but do not have array methods like filter or map. These are called “array-like objects.” By using the spread syntax [...] to convert them into pure arrays, you can fully utilize the powerful array manipulation methods of JavaScript. This article explains how to use this technique with an attendance management system as an example.
Specifications (Input/Output)
Conversion via Spread Syntax
| Syntax | Meaning | Return Value |
| […object] | Expands an iterable object and stores elements in a new array. | Array (Real Array) |
- Input:
NodeList,HTMLCollection,String,arguments, etc. - Output: A standard array containing the input elements.
- Advantage: Enables the use of array-specific methods such as
filter,map, andreduce.
Basic Usage
1. Converting NodeList
This is the most common pattern in DOM manipulation. Since the value returned by querySelectorAll is not an array, you cannot use filter on it directly.
// Get a NodeList (not an array)
const divList = document.querySelectorAll('div');
// Convert to an array
const divArray = [...divList];
// Now you can use array methods
const activeDivs = divArray.filter(div => div.classList.contains('active'));
2. Converting Strings
This breaks a string down into an array of individual characters.
const text = "Hello";
const chars = [...text];
console.log(chars); // ["H", "e", "l", "l", "o"]
Full Code (HTML / JavaScript)
This program extracts only members with the “attend” class from an HTML element list on an attendance management screen and displays their names.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Attendance Checker</title>
<style>
.panel {
font-family: 'Segoe UI', sans-serif;
border: 1px solid #ccc;
padding: 20px;
max-width: 400px;
background-color: #f9f9f9;
}
.member-card {
padding: 10px;
margin: 5px 0;
border: 1px solid #ddd;
background-color: white;
border-radius: 4px;
color: #555;
}
.member-card.attend {
border-left: 5px solid #4CAF50;
font-weight: bold;
color: #2e7d32;
}
.member-card.absent {
border-left: 5px solid #ccc;
background-color: #eee;
}
.btn-check {
margin-top: 15px;
padding: 10px 20px;
background-color: #2196F3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
.btn-check:hover { background-color: #1976D2; }
.result-box {
margin-top: 15px;
padding: 10px;
background-color: #e3f2fd;
border-radius: 4px;
min-height: 1.5em;
}
</style>
</head>
<body>
<div class="panel">
<h3>Meeting Member List</h3>
<div id="member-container">
<div class="member-card attend">Mori</div>
<div class="member-card absent">Komori</div>
<div class="member-card attend">Nakamori</div>
<div class="member-card attend">Omori</div>
<div class="member-card absent">Hayashi</div>
</div>
<button id="btn-extract" class="btn-check">Extract Attendees (filter)</button>
<div id="output-area" class="result-box">
Results will appear here.
</div>
</div>
<script src="converter.js"></script>
</body>
</html>
JavaScript
/**
* Attendee Extraction Script
* Converting NodeList to an array to use the filter method
*/
const extractButton = document.getElementById('btn-extract');
const outputArea = document.getElementById('output-area');
/**
* Logic to extract and display attendees
*/
const extractAttendees = () => {
// 1. Get NodeList (filter cannot be used directly)
const allMembersNodeList = document.querySelectorAll('.member-card');
// 2. Convert to a real array using spread syntax
const allMembersArray = [...allMembersNodeList];
// 3. Use array method: filter
// Extract only elements containing the 'attend' class
const attendingMembers = allMembersArray.filter((element) => {
return element.classList.contains('attend');
});
// 4. Use map to extract text names
const memberNames = attendingMembers.map((element) => {
return element.textContent.trim();
});
// Display results
if (memberNames.length > 0) {
outputArea.textContent = `Attendees (${memberNames.length}): ${memberNames.join(', ')}`;
} else {
outputArea.textContent = 'No attendees found.';
}
};
extractButton.addEventListener('click', extractAttendees);
Custom Points
You can also use Array.from(list) instead of [...list]. The advantage of Array.from is that it allows you to pass a mapping function as a second argument, like Array.from(list, element => element.textContent). If you want to exclude specific elements, you can change the filter condition to something like !element.classList.contains('absent').
Cautions
Spread syntax [...] does not work in Internet Explorer (IE). If you need to support legacy browsers, use the older Array.prototype.slice.call(nodeList) method or a transpiler like Babel. Regarding performance, if you have tens of thousands of elements, copying them into a new array consumes memory and time. For very simple loops, it may be faster to iterate directly over the NodeList using a for...of loop without converting it.
Advanced Usage
When handling variable arguments inside a function, converting the arguments object into an array makes it easier to manipulate. While “rest parameters” (...args) are now recommended, this technique is helpful when reading older code.
function sumAll() {
// Convert arguments object to array
const args = [...arguments];
// Calculate total using reduce
return args.reduce((sum, num) => sum + num, 0);
}
console.log(sumAll(10, 20, 30)); // 60
Summary
In web development, the need to filter or map elements obtained with querySelectorAll is common. Mastery of this flow—getting a NodeList, converting it with [...NodeList], and then applying array methods—will significantly improve your efficiency in DOM manipulation.
