在 DOM(文档对象模型)中,有许多类数组(Array-like)对象。它们类似于数组,可以使用索引访问元素,也有 length 属性,但不能直接使用数组方法(如 pushpopmap 等)。以下是常见的 DOM 类数组对象:

**📌 总结:

类数组对象 来源 动态更新 支持 forEach 转换数组方法
NodeList querySelectorAllchildNodes 部分动态(childNodes是动态的) Array.from()[...]
HTMLCollection getElementsByTagNamechildren ✅ 是 Array.from()[...]
DOMTokenList classList ✅ 是 Array.from()[...]
NamedNodeMap attributes ✅ 是 Array.from()[...]
RadioNodeList form.elements ✅ 是 Array.from()[...]
FileList <input type="file">.files ❌ 否 Array.from()[...]

📌 1. NodeList

来源

  • document.querySelectorAll()

  • element.childNodes

特点

  • 静态 NodeList(如 querySelectorAll 返回的)不会随 DOM 变化自动更新。

  • 动态 NodeList(如 childNodes)会实时反映 DOM 的变化。

示例


const divs = document.querySelectorAll('div'); // 静态 NodeList
const children = document.body.childNodes;     // 动态 NodeList

console.log(divs.length); // 可以获取长度
divs.forEach(div => console.log(div)); // 支持 forEach
// divs.map(...) // ❌ 报错,不能直接使用数组方法

转换数组

const divArray = Array.from(divs); // 或 [...divs]

📌 2. HTMLCollection

来源

  • document.getElementsByClassName()

  • document.getElementsByTagName()

  • element.children

特点

  • 动态集合,会实时反映 DOM 的变化。

  • 只有 length 和索引访问,没有 forEach 等数组方法。

示例

const divs = document.getElementsByTagName('div'); // HTMLCollection
console.log(divs.length); // 可以获取长度
// divs.forEach(...) // ❌ 报错,没有 forEach
for (let i = 0; i < divs.length; i++) {
    console.log(divs[i]); // 用索引访问
}

转换数组

const divArray = Array.from(divs); // 或 [...divs]

📌 3. DOMTokenList

来源

  • element.classList

特点

  • 表示元素的类名列表(如 class="btn active")。

  • 有 add()remove()toggle()contains() 方法。

  • 支持 forEach,但没有 mapfilter

示例

const btn = document.querySelector('button');
const classes = btn.classList; // DOMTokenList

classes.add('new-class'); // 添加类
classes.remove('old-class'); // 移除类
classes.forEach(cls => console.log(cls)); // 支持 forEach

转换数组

const classArray = Array.from(classes); // 或 [...classes]


📌 4. NamedNodeMap

来源

  • element.attributes

特点

  • 表示元素的所有属性(如 <div id="box" class="red"> 的 id 和 class)。

  • 可以通过 getNamedItem() 获取属性。

示例

const div = document.querySelector('div');
const attrs = div.attributes; // NamedNodeMap

console.log(attrs.length); // 属性数量
console.log(attrs.getNamedItem('class').value); // "red"

转换数组

const attrArray = Array.from(attrs); // 或 [...attrs]


📌 5. RadioNodeList

来源

  • formElement.elements(表单控件集合)

特点

  • 针对 <input type="radio"> 和 <input type="checkbox"> 的集合。

  • 可以直接获取选中的值(value)。

示例

<form id="myForm">
    <input type="radio" name="gender" value="male"> Male
    <input type="radio" name="gender" value="female"> Female
</form>

const form = document.getElementById('myForm');
const genders = form.elements['gender']; // RadioNodeList

console.log(genders.value); // 获取选中的值(如 "male")

转换数组

javascript

const genderArray = Array.from(genders); // 或 [...genders]


📌 6. FileList

来源

  • <input type="file"> 的 files 属性

特点

  • 表示用户选择的文件列表。

  • 可以通过索引访问文件(File 对象)。

示例

<input type="file" id="fileInput" multiple>
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (e) => {
    const files = e.target.files; // FileList
    console.log(files[0].name); // 第一个文件名
});

转换数组

javascript

const fileArray = Array.from(files); // 或 [...files]


🎯 如何操作类数组?

  1. 遍历

    • for 循环

    • for...of(推荐)

    • forEach(如果支持,如 NodeListDOMTokenList

  2. 转数组

    • Array.from()

    • [...arrayLike]

  3. 调用数组方法

    javascript

    const divs = document.querySelectorAll('div');
    const divTexts = Array.from(divs).map(div => div.textContent);


💡 注意事项

  • HTMLCollection 和动态 NodeList 会实时更新,如果在循环中修改 DOM 可能会导致问题。

  • 尽量使用 querySelectorAll(返回静态 NodeList),避免 getElementsBy*(返回动态 HTMLCollection)。

  • 现代浏览器支持 NodeList.forEach,但旧版 IE 不支持。

现在你可以轻松区分和操作这些 DOM 类数组对象了! 🚀