前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库arguments 转数组的方法对比
JSJavaScript函数与作用域

如何将函数内的 arguments 对象转换为真正的数组?各方法有何不同?

三种主流方式:Array.prototype.slice.call、Array.from、展开运算符。都能把类数组的 arguments 拷成真数组,区别在兼容性、可读性和稀疏性处理;注意箭头函数没有 arguments。

前端进阶之旅 · 一题精讲更新于 2026.09.05
JavaScript#函数与作用域
先看核心答案读代码示例
理解线索

三方法的选择线索

  1. slice.call借用数组原型方法浅拷贝,ES3 时代就可用
  2. Array.fromES6 引入,接受类数组与可迭代对象
  3. 展开运算符依赖 arguments 的迭代器,语法最短

新代码优先剩余参数,只有维护旧函数时才需要转换 arguments。

核心回答

先记住这个答案

arguments 是类数组对象,有 length 和数字索引,但没有 map、filter 等数组方法。转真数组常用三招:Array.prototype.slice.call(arguments) 靠借用数组方法做浅拷贝,兼容性最好;Array.from(arguments) 语义最清晰,专为类数组和可迭代对象设计;[...arguments] 利用 arguments 自带的 Symbol.iterator 展开,最简洁。三者都是浅拷贝,性能差距在常规规模下可忽略,按可读性选即可。更简单做法是直接用剩余参数 ...args 声明,天生就是数组。

  • slice.call 兼容老环境,Array.from 语义最清晰
  • 展开运算符依赖 Symbol.iterator,写法最简
  • 箭头函数没有 arguments,应用剩余参数

三种转换方式的机制差异

arguments 是类数组对象:有 length、有从 0 开始的索引,也实现了 Symbol.iterator,但原型链上没有数组方法。Array.prototype.slice.call(arguments) 的原理是把 slice 的 this 指向 arguments,slice 内部只依赖 length 和索引读取元素,因此对任何类数组都成立,这也是它能在 ES6 之前通行的原因。

Array.from 是 ES6 专门为类数组和可迭代对象设计的工厂方法,语义最直白,还能传第二个映射参数一次完成转换加处理。[...arguments] 走的是迭代协议,逐项调用迭代器取值。三者产生的都是浅拷贝新数组,元素引用与原值共享;对稀疏的 arguments(实参少于形参时不会出现空槽,因为只记录实参)差异不大,性能在常见参数规模下没有可感知差距。

三种转换方式对比JavaScript
function demo(a, b) {
  const bySlice = Array.prototype.slice.call(arguments);
  const byFrom = Array.from(arguments);
  const bySpread = [...arguments];
  console.log(Array.isArray(bySlice), Array.isArray(byFrom), Array.isArray(bySpread));
  console.log(JSON.stringify(bySlice));
  console.log(JSON.stringify(byFrom.map(x => x * 2)));
  console.log(JSON.stringify(bySpread));
}
demo(1, 2, 3);
查看输出与解释
true true true
[1,2,3]
[2,4,6]
[1,2,3]

在任意现代浏览器控制台或 Node 环境可直接运行,三种方式均得到真数组且内容一致。

可变参数日志函数的选型决策

维护一个 ES5 时代的老项目,其中 log(level) 后接任意多个消息片段,构建工具不能引入 ES6 语法,因为目标环境包含旧浏览器。输入是 log('info', 'user', 42, 'login') 这类不定参数,约束是必须跳过第一个参数再拼接。此时只能选 Array.prototype.slice.call(arguments, 1),一次调用完成转数组加截断,结果是得到可 join 的真数组。

如果同一功能写在新代码里,决策应改为 function log(level, ...msgs):msgs 天生是数组,无需转换,也不会出现「忘记转换直接调用 msgs.join 报 TypeError」的问题。选择依据不是性能,而是语法可用性与出错概率:转换是补救手段,剩余参数才是源头解法。

容易失效的条件与替代方案

最常见的失败场景是在箭头函数里访问 arguments:箭头函数不创建自己的 arguments,读到的是外层普通函数的 arguments,外层也没有时直接抛 ReferenceError。另一个边界是含默认参数、剩余参数或解构参数的非严格函数,以及所有严格模式函数:arguments 不再与形参同步,修改转换出的数组或 arguments 互不影响,依赖同步逻辑会出错。

对应处理:箭头函数内改用剩余参数收集实参,或显式引用外层具名函数的 arguments;需要「参数别名」效果时应直接操作形参变量而非 arguments。代价是放弃了 arguments 的神秘同步行为,换来的是严格模式下可预测、引擎更容易优化的代码。

回答前,多想一步

容易答错的地方

arguments 是数组的一种
typeof arguments 是 'object',它没有数组原型方法,直接调 arguments.map 会抛 TypeError。它只是类数组且可迭代,必须先转换或改用剩余参数。
slice.call 性能远超其他方法
现代引擎对三种方式都有优化,常规参数数量下耗时差异不可测。选型应按兼容性和可读性:老环境用 slice.call,新环境用 Array.from 或展开运算符。
试着用自己的话回答

面试官还会怎么问?

为什么新代码推荐剩余参数而不是转换 arguments?

剩余参数 ...args 声明后就是真数组,无需转换,且不与形参产生同步关系,行为可预测。箭头函数也能用,而 arguments 在箭头函数中不可用。

转换后的数组和原 arguments 会互相影响吗?

不会。三种方式都是浅拷贝:数组结构独立,增删元素互不影响;但元素若是对象,引用共享,改对象属性两边可见。

arguments 有 Symbol.iterator 意味着什么?

意味着它可迭代,能被 for...of、展开运算符和 Array.from 直接消费。这也是 [...arguments] 成立而 [...{length:2,'0':'a'}] 这类纯类数组失败的原因。

从一道题,走向一组知识

把知识连起来

函数与作用域

JavaScript 剩余参数(rest parameters)与 arguments 对象相比有哪些优势?

剩余参数是 arguments 转数组问题的现代替代方案,可直接对比两者优劣。

函数与作用域

箭头函数为什么没有自己的 arguments 对象?如何获取所在外层函数的 arguments?

解释箭头函数无 arguments 的机制,以及如何在箭头函数中获取外层实参。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • The arguments object

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 三种转换方式的机制差异
  3. 可变参数日志函数的选型决策
  4. 容易失效的条件与替代方案
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑