Array.prototype.slice.call(arrayLike)可将类数组转为真数组,因其仅依赖length属性和数字索引,不校验Array实例,故零依赖、兼容IE6+、性能优。

直接用 Array.prototype.slice.call(arrayLike) 即可将类数组对象(如 arguments、NodeList、HTMLCollection)转为真数组,无需引入任何外部库,性能接近原生循环,且兼容性极佳(IE6+ 支持)。
为什么 slice 能“零依赖”转换类数组?
slice 方法本身不校验调用者是否为 Array 实例,只依赖两个关键条件:存在 length 属性 和 拥有按数字索引排列的可读属性。只要类数组满足这两点(例如 {0: 'a', 1: 'b', length: 2}),slice 就能按索引逐个读取并装入新数组。
它不修改原对象,也不依赖 Symbol.iterator 或 Array.from 的 polyfill,因此真正“零依赖”。
最简写法与常见调用方式
推荐以下三种稳定写法(按优先级排序):
-
Array.prototype.slice.call(obj)—— 兼容性最好,适用于所有 ES3+ 环境 -
[].slice.call(obj)—— 更短,本质相同,但需注意空数组字面量在严格模式下无副作用 -
Array.prototype.slice.apply(obj)—— 等价,但不如call直观,一般不推荐
示例:
function foo() {
const args = Array.prototype.slice.call(arguments); // → ['a', 'b', 'c']
return args.map(x => x + '!');
}
foo('a', 'b', 'c');
对比现代替代方案的取舍
虽然 Array.from() 和展开运算符([...obj])更语义化,但有明确限制:
-
Array.from需要 polyfill 才能在 IE 中运行,且内部做了额外类型检查和映射逻辑,开销略高 - 展开运算符要求对象具有
Symbol.iterator,而原生NodeList(尤其旧版 DOM)可能不实现迭代器,导致报错 -
slice.call在 Chrome/Firefox/Edge/IE 中均被高度优化,V8 甚至对常见类数组(如arguments)做了内联快路径
注意事项与边界情况
不是所有“像数组”的对象都适用:
- 必须有
length,且为非负整数;若length === 0或undefined,结果为空数组或TypeError - 索引属性必须是字符串化的自然数(
'0'、'1'),'-1'或'01'不会被识别 - 稀疏类数组(如
{0: 'a', 2: 'c', length: 3})会生成['a', undefined, 'c'],符合预期 - 避免对超大类数组(如百万级
getElementsByClassName结果)频繁调用,可考虑分片或流式处理


















