函数的length属性表示从左到右第一个带默认值参数前的普通形参个数,纯属语法解析规则,与运行时参数传递无关;例如function(a,b=1){}的length为1,因a在b前且b带默认值。

函数的 length 属性不是“最少要传几个参数”,而是“从左到右数,第一个带默认值的参数之前有多少个普通形参”——它只看函数定义的语法结构,不参与运行时逻辑。
为什么 function(a, b = 1) {} 的 length 是 1
JavaScript 的 length 从左开始扫描形参列表,遇到第一个带默认值的参数(b = 1)就停止计数,前面的 a 被计入,后面的全忽略。这不是“必填参数个数”的语义判断,纯属语法解析规则。
-
function(a, b, c = 2) {}→length === 2 -
function(a = 1, b) {}→length === 0(a自身带默认值,左侧无非默认参数) -
function([x, y] = [0, 0]) {}→length === 1(解构参数本身算一个形参,且带默认值,所以左侧无非默认参数) -
function(...args) {}→length === 0(剩余参数不贡献长度,且它前面没参数)
length 和调用时实际传参完全无关
它既不强制你必须传够 length 个参数,也不阻止你多传、少传或跳过带默认值的参数。运行时行为由 arguments、默认值赋值逻辑、剩余参数展开等机制决定,length 不参与其中。
-
function foo(a, b = 2) {},foo.length === 1,但foo()、foo(1)、foo(1, 3)全都合法 -
foo()中a是undefined,不是因为length为 1 就“应该传”,而是 JS 本身允许缺省 - 没有引擎会根据
length报错或自动补值——TypeScript 或 JSDoc 的检查是额外层,不是 JS 运行时行为
bind 和箭头函数的 length 也遵循同一套规则
绑定函数的 length 是基于原函数 length 减去已绑定的前置参数个数,但仅限于显式绑定在前面的实参;箭头函数则完全按其形参声明计算,和普通函数一致。
-
const add = (a, b) => a + b;→add.length === 2 -
const add5 = add.bind(null, 5);→add5.length === 1(原length是 2,绑了 1 个前置参数) -
const empty = () => {};→empty.length === 0 -
const partial = add.bind(null, 5, 6);→partial.length === 0(2 - 2 = 0)
真正容易被忽略的是:这个属性在严格模式下不能被修改,但它本身不构成任何契约约束;你在写工具函数或类型推导时若把它当“最小必传数”用,就会漏掉默认参数在中间或开头的情况——比如 function f(x = 1, y) {},f.length === 0,但 y 实际上根本没法单独传进去,因为 x 在前且可省略,JS 会把第一个实参自动赋给 x。










