函数的 length 属性
函数实例的 length 表示首个默认参数之前的形参个数,不计 rest;解构参数整体计一个,常用于柯里化和函数式编程。
#frontend
#javascript
#ecmascript
#concept
#evergreen
[!info] related notes
- 所属 MOC: ECMAScript MOC
- 前置概念: ECMAScript 函数
- 相关概念: currying, rest-parameters-and-spread-operator, call-apply-bind
函数的 length 属性
一句话定义
函数对象的 length 表示首个默认参数之前的形参个数,不计 rest;解构参数整体计一个。Function.prototype.length 本身为 0,具体函数通常有自己的 length 属性。
核心机制
基本行为
function fn(a, b, c) {}
console.log(fn.length); // 3
function fn2(a, b, c = 1) {}
console.log(fn2.length); // 2
function fn3(...args) {}
console.log(fn3.length); // 0
关键规则
- 只计算形参:不计算实际传入的参数数量
- 不包括默认参数:有默认值的参数不计入
- 不包括剩余参数:
...rest参数不计入 - 从第一个有默认值的参数开始停止计数
详细示例
// 1. 普通函数
function add(a, b) { return a + b; }
console.log(add.length); // 2
// 2. 有默认值的参数
function greet(name, greeting = 'Hello') {
return `${greeting}, ${name}`;
}
console.log(greet.length); // 1
// 3. 剩余参数
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum.length); // 0
// 4. 混合情况
function mixed(a, b = 1, c, d = 2) {
return a + b + c + d;
}
console.log(mixed.length); // 1(从第一个默认参数 b 开始停止计数)
// 5. 箭头函数
const arrowFn = (a, b, c) => a + b + c;
console.log(arrowFn.length); // 3
// 6. bind() 返回的函数
const boundFn = add.bind(null, 1);
console.log(boundFn.length); // 1(剩余参数数量)
实际应用
1. 柯里化实现
只在约定固定元数时,才可用 length 判断柯里化何时执行。带默认值/rest 的函数通常需要显式指定目标元数;length 不是必填参数 schema:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.call(this, ...args);
}
return curried.bind(this, ...args);
};
}
const add = (a, b, c) => a + b + c;
console.log(add.length); // 3
const curriedAdd = curry(add);
curriedAdd(1)(2)(3); // 6
2. 参数验证
下面只检查传参数量是否达到 fn.length,不验证类型、业务必填或参数值;显式传 undefined 也计入实参数量:
function validateArgs(fn, ...args) {
if (args.length < fn.length) {
throw new Error(`需要 ${fn.length} 个参数,但只传入了 ${args.length} 个`);
}
return fn(...args);
}
3. 不能靠源码字符串推断签名
fn.length 不是完整签名。用 fn.toString().includes(’…’) 检测 rest 会把函数体中的展开、字符串或注释误算;绑定函数、原生函数与转译代码也不适用。确需元数或参数 schema 时应显式声明,不从源码片段猜测。
常见误解
1. 与 arguments.length 的区别
function fn(a, b) {
console.log(fn.length); // 2(定义时的形参数量)
console.log(arguments.length); // 3(调用时的实参数量)
}
fn(1, 2, 3);
2. 箭头函数没有 arguments
const arrowFn = (a, b) => {
// console.log(arguments); // 只有外层不存在此绑定时才会 ReferenceError
console.log(arrowFn.length); // 2
};
3. 默认参数的影响
// ❌ 错误理解:认为是 3
function fn(a, b = 1, c) {}
console.log(fn.length); // 1
// ✅ 正确理解:从第一个默认参数开始停止计数
// fn.length 只计算 a,不计算 b 和 c
BFE.dev 相关题目
- 1. implement curry():使用
fn.length判断参数数量 - 19. this:理解函数调用时的参数传递
面试要点
- 基本概念:知道
length返回定义时的形参数量 - 默认参数:理解默认参数不计入
length - 剩余参数:理解剩余参数不计入
length - 柯里化应用:知道如何在柯里化中使用
length - 与 arguments.length 的区别:能区分两者