array.prototype.slice.call能转换类数组因其不校验this是否为真数组,仅依赖数字索引和length属性;arguments等类数组满足该条件,slice便按索引读取生成新数组,且不修改原对象。

为什么 Array.prototype.slice.call 能转类数组
因为 slice 方法本身不校验 this 是否为真数组,只依赖两个关键行为:有数字索引 + 有 length 属性。类数组对象(比如函数内的 arguments)恰好满足——它有 arguments[0]、arguments[1] 和 arguments.length,slice 就能按索引逐个读取并返回新数组。
注意:slice 是“非破坏性”操作,不会修改原对象,这点和 Array.from 一致,但底层机制更轻量。
arguments 场景下最简写法及常见翻车点
在传统函数中直接用 Array.prototype.slice.call(arguments) 最稳妥:
function sum() {
const args = Array.prototype.slice.call(arguments);
return args.reduce((a, b) => a + b, 0);
}
容易踩的坑:
-
arguments在箭头函数里不存在,此法在箭头函数中会报ReferenceError: arguments is not defined - ES6+ 应优先用剩余参数
...args替代,更语义化且无兼容性问题 - 若传入
null或undefined作第一个参数,会抛TypeError: Cannot convert undefined or null to object
替代方案对比:Array.from vs slice.call
Array.from 是现代标准写法,支持任意可迭代对象(包括 NodeList、Map.keys()),而 slice.call 只适用于类数组(必须含 length + 数字索引)。
性能上差异极小,但语义和健壮性不同:
-
Array.from(arguments)对arguments安全,即使length为undefined也会返回空数组 -
Array.prototype.slice.call(arguments)遇到length: undefined会静默返回空数组,但遇到length: NaN会返回[],行为不够直观 -
slice.call在 IE9+ 全兼容;Array.from需 IE12+ 或垫片
其他类数组对象的实操注意事项
除了 arguments,常见类数组还有 document.querySelectorAll() 返回的 NodeList(较新浏览器已可迭代)、HTMLCollection 等:
-
NodeList在旧版 Safari 中不支持Array.from,此时slice.call仍是 fallback 首选 -
HTMLCollection没有forEach,必须转数组才能链式调用,slice.call(coll)比[].slice.call(coll)更明确意图 - 自定义类数组若漏写
length,slice.call会返回空数组,建议加一层校验:obj && typeof obj.length === 'number'
真正麻烦的不是转换动作本身,而是判断“它到底算不算类数组”——有些对象看起来像(比如有 0、1 键),但缺 length 或键名不是纯数字,这时 slice.call 就会失效。










