什么是 JavaScript 的类数组对象?如何转化为数组?
JavaScript 类数组对象什么是类数组对象类数组对象是具备数组外观但不是真正数组的对象满足两个条件有length属性值为非负整数元素以0, 1, 2...数字索引作为键名constarrayLike{0:a,1:b,2:c,length:3};// 看起来像数组实际是普通对象arrayLike[0];// aarrayLike.length;// 3Array.isArray(arrayLike);// falsearrayLike.map;// undefined —— 没有数组方法常见的类数组对象来源示例函数的argumentsfunction f() { arguments }DOM 的NodeListdocument.querySelectorAll(div)DOM 的HTMLCollectiondocument.forms字符串abc有 length 和索引自定义对象{ 0: x, 1: y, length: 2 }functionfoo(){console.log(typeofarguments.map);// undefinedconsole.log(arguments.length);// 实参数量}foo(1,2,3);转化为数组的方法1.Array.from()— 最推荐constarrArray.from(arrayLike);// [ a, b, c ]语义清晰ES6 标准支持第二个参数映射函数类似mapArray.from(arrayLike,xx.toUpperCase());// [ A, B, C ]2. 展开运算符...constarr[...arrayLike];// [ a, b, c ]最简洁需确保对象是可迭代对象iterablearguments、NodeList可用但自定义类数组对象必须实现[Symbol.iterator]否则报错// 自定义类数组对象没有迭代器展开会报错constlike{0:a,1:b,length:2};[...like];// TypeError: like is not iterable// 需手动添加迭代器like[Symbol.iterator]function*(){for(leti0;ithis.length;i)yieldthis[i];};[...like];// [a, b]3.Array.prototype.slice.call()constarrArray.prototype.slice.call(arrayLike);// [ a, b, c ]ES5 经典写法兼容性最好简写形式[].slice.call(arrayLike)4.Array.prototype.forEach/map借用// 借用 forEach 遍历同时构建新数组constarr[];Array.prototype.forEach.call(arrayLike,itemarr.push(item));本质是借用数组方法不是真正的转换5. 循环遍历构建constarr[];for(leti0;iarrayLike.length;i){arr.push(arrayLike[i]);}最原始适用于任何场景但代码冗长6.Object.values()— 有局限constarrObject.values(arrayLike);// [ a, b, c ]只取值丢弃索引对应关系如果对象有非数字键或 length 属性结果会包含多余值不可靠constlike{0:a,1:b,length:2,name:extra};Object.values(like);// [a, b, 2, extra] ← 混入了 length 和 name方法对比方法兼容性可读性自定义对象额外能力Array.from()ES6优支持映射函数[...obj]ES6优需iterator无slice.call()ES5中支持无循环遍历全部差支持无Object.values()ES8中不可靠无实际场景// arguments 转数组functionsum(){returnArray.from(arguments).reduce((a,b)ab,0);}// NodeList 转数组constdivsArray.from(document.querySelectorAll(div));divs.forEach(dd.classList.add(active));// 配合解构赋值functionfirst(){const[first][...arguments];returnfirst;}一句话总结类数组有 length 和数字索引但不是数组Array.from()是最通用最推荐的转换方式[...]最简洁但要求可迭代。