函数的length属性只统计定义时左侧连续的普通形参个数,遇默认值或rest参数即停止;rest参数本身不计入,且必须位于形参末尾。

函数的 length 属性不反映你调用时传了多少个参数,它只看函数定义时“左边一串没被默认值或 rest 打断”的形参个数。REST 参数(...args)会直接终止计数,它本身不算,它前面的参数照常计入——但前提是那些参数没被默认值提前截断。
REST 参数让 length 只算它前面的普通形参
REST 参数是语法上的“分界点”,length 统计到它出现的位置就停止,不再往后看:
-
function fn(a, b, ...rest) {}→fn.length === 2(a和b是普通形参,...rest不计) -
function fn(...rest) {}→fn.length === 0(前面没有普通形参) -
function fn(x = 1, ...rest) {}→fn.length === 0(第一个形参就有默认值,计数立即停止)
REST 参数和默认参数叠加时,谁先出现谁主导
length 的计算顺序是:从左到右扫描形参列表,遇到第一个“非普通”形参(即带默认值的参数,或 ... 开头的 rest 参数)就停。哪个在左,哪个就起决定作用:
-
function fn(a, b = 2, ...rest) {}→length === 1(b = 2是第一个非普通形参,a被计入,...rest不影响结果) -
function fn(a, ...rest, b) {}→ 语法错误(REST 参数必须在最后,这种写法根本无法通过解析) -
function fn(...rest, a = 1) {}→ 同样非法(REST 必须结尾,不能有后续形参)
别把 length 当成“最少要传几个”
length 是静态描述,不是运行约束。哪怕 fn.length === 0,你仍可以传任意多实参,JS 完全允许:
-
function logAll(...msgs) {}→logAll.length === 0,但logAll('a')、logAll('a','b','c')都合法 - 它不影响
arguments.length或msgs.length的实际值,那才是运行时真实传入的数量 - 工具函数或类型检查若仅依赖
length判断必填项,会漏掉 REST 场景下的灵活性
这个属性设计初衷就是提供一种轻量的元信息,用于函数签名推导或调试辅助,不是契约依据。











