前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库arguments 与形参(parameters)的区别
JavaScript函数与作用域

arguments 和函数的形参是一回事吗?改了一个另一个会变吗?

形参是你在函数声明里起的变量名,arguments 是这次调用实际传进来的全部值。两者数量可以不一样,也基本互不影响,只有在非严格模式、参数里没有默认值和解构、也没有 rest 时,改 arguments[0] 才会顺带改掉第一个形参。

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

声明时的名字和调用时的值

  1. 形参 parameter声明里写的变量名,可以带默认值、解构、rest
  2. 实参 argument调用时真正传进来的值,全部按位置记在 arguments 里
  3. 映射老规则,非严格且参数简单时,形参和 arguments 下标双向同步

默认值不会写进 arguments。调用 f() 时形参拿到了默认值,但 arguments.length 仍然是 0。

核心回答

先记住这个答案

形参是函数声明里写的变量名,属于函数的局部变量;arguments 是每次调用时生成的一个类数组对象,按位置记录这次实际传进来的全部值。所以形参写了两个,调用时传五个,arguments.length 就是 5;传一个,第二个形参就是 undefined。两者一般互不影响,只有在非严格模式、参数列表里没有默认值、解构和 rest 时,改 arguments[0] 才会同步改掉第一个形参,反过来也一样。

  • 形参看声明,arguments 看这次调用实际传了什么
  • fn.length 数的是形参,arguments.length 数的是实参
  • 只有非严格且参数列表简单时,两者才会联动
  • 新代码用 rest 参数代替 arguments

改 arguments[0] 会不会改到形参

这是面试最爱问的一个细节。同样一句 arguments[0] = 7,放在三种函数里结果不一样。

三种函数的对比JavaScript
function loose(a) {
  arguments[0] = 7 // 非严格 + 简单参数:会联动 a
  return a
}
function strict(a) {
  'use strict'
  arguments[0] = 7 // 严格模式:各改各的
  return a
}
function withDefault(a = 1) {
  arguments[0] = 7 // 有默认值:各改各的
  return a
}
console.log(loose(2), strict(2), withDefault(2))
查看输出与解释
7 2 2

只有第一个函数返回了 7。早期 JavaScript 为了实现方便,把形参和 arguments 的下标做成了同一块存储的两个名字,改一个另一个就变。这个行为很反直觉,所以严格模式把它去掉了;后来加的默认值、解构、rest 这些「非简单参数」也一律不联动。 实际项目里这条规则的意义在于:别依赖它。比如一个老函数靠改 arguments[0] 来修正参数,某天有人给形参加了个默认值,联动悄悄失效,结果就变了,而且很难查。

函数 length 和 arguments.length 的区别

两个 length 名字一样,一个看声明,一个看调用,是面试常见陷阱。

两个 length 分别数什么JavaScript
function f(a, b = 2, ...rest) {
  console.log(arguments.length, a) // 这次调用传了几个值
}
console.log(f.length) // 声明里的形参个数
f()
f(1, 2, 3, 4)
查看输出与解释
1
0 undefined
4 1

f.length 是 1,因为它只数第一个带默认值的参数之前的形参,rest 参数也不算。这个值在函数定义时就定了,和怎么调用无关。 arguments.length 每次调用都不同。f() 时是 0,这里能看出默认值不会写进 arguments。形参 b 在函数里是 2,但 arguments[1] 仍是 undefined。f(1, 2, 3, 4) 时是 4,多传的值即使没有形参接收,也都在 arguments 里。

什么时候会用到 fn.length
柯里化会用 fn.length 判断参数凑够了没有。所以被柯里化的函数如果带默认值,length 变小,柯里化就会提前执行,这是一个真实会踩的坑。

现在为什么推荐用 rest 参数

arguments 是类数组:有下标和 length,但不是真数组,不能直接调 map、filter。箭头函数里也没有自己的 arguments,读到的是外层普通函数的。

rest 参数 (...args) 解决了这几个问题。args 是真正的数组,只收集剩下的参数,箭头函数里也能用,TypeScript 还能给它标元组类型。所以新代码里需要不定数量参数时,直接写 rest,arguments 只在读老代码时需要认识。

回答前,多想一步

容易答错的地方

把 fn.length 当成传了几个参数
fn.length 来自函数声明,而且遇到默认值和 rest 会提前停止计数。想知道这次调用传了几个,要在函数里看 arguments.length 或者 args.length。
以为严格模式下不能用 arguments
严格模式下照样能读下标和 length,只是不再和形参联动,另外访问 arguments.callee 会抛 TypeError。
以为 arguments 里会有默认值
默认值只作用于形参。没传的位置在 arguments 里就是没有,arguments.length 也不会把它算进去。
试着用自己的话回答

面试官还会怎么问?

怎么把 arguments 转成真正的数组?

Array.from(arguments) 或 [...arguments] 最直接,老代码里常见的是 Array.prototype.slice.call(arguments)。不过更好的办法是一开始就写成 rest 参数。

arguments 能用 for...of 遍历吗?

能。普通函数里的 arguments 实现了 Symbol.iterator,所以可以 for...of,也可以展开。但它的原型还是 Object.prototype,Array.isArray(arguments) 返回 false。

为什么 TypeScript 项目里基本不用 arguments?

arguments 的类型是 IArguments,每一项都是 any,和形参的类型也对不上。rest 参数可以写成 ...args: [string, number] 这样的元组类型,调用方传错了编译期就能发现。

从一道题,走向一组知识

把知识连起来

手写与交互性能

防抖和节流有什么区别?

手写防抖时要把本次调用的参数存下来留给延迟执行的函数用,最早的写法就是 arguments。

作用域与函数

JavaScript 闭包是什么?

箭头函数里读 arguments 拿到的是外层函数的,这和闭包按定义位置查找变量是同一套规则。

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

参考资料

  • The arguments object

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

本题目录
  1. 先记住这个答案
  2. 改 arguments[0] 会不会改到形参
  3. 函数 length 和 arguments.length 的区别
  4. 现在为什么推荐用 rest 参数
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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