当前位置: 首页 > news >正文

8.5JavaScript函数 arguments

一、arguments 详解

1. 什么是 arguments

  • arguments 是一个类数组对象(array-like object),存在于非箭头函数的函数作用域中。
  • 它包含了调用函数时传入的所有实参,即使函数定义时没有声明形参。
  • 它具有 length 属性,可以通过索引访问(如 arguments[0]),但不具备数组的方法(如 .map().forEach() 等)。

2. 基本用法示例

function foo(a, b) {console.log(arguments.length); // 实参个数console.log(arguments[0]);     // 第一个实参console.log(arguments[1]);     // 第二个实参console.log(arguments[2]);     // 第三个实参(即使没定义形参)
}foo(1, 2, 3); 
// 输出: 3, 1, 2, 3

3. arguments 的特性

  • 与形参绑定(在非严格模式下)

    function test(a) {console.log(a, arguments[0]); // 1, 1a = 2;console.log(a, arguments[0]); // 2, 2(非严格模式下会同步)
    }
    test(1);

    ⚠️ 在 严格模式('use strict') 下,这种绑定被解除,修改 a 不会影响 arguments[0]

  • 不是真正的数组

    function foo() {console.log(Array.isArray(arguments)); // false// arguments.map(x => x * 2); // 报错!
    }
  • 箭头函数中没有 arguments

    const arrow = () => {console.log(arguments); // ReferenceError: arguments is not defined
    };

二、严格模式下 arguments 仍然存在

'use strict';function foo(a, b) {console.log(arguments[0]); // 正常访问console.log(arguments.length); // 正常
}foo(1, 2); // 输出: 1, 2

结论arguments 在严格模式下依然可用,不是被禁用的对象。


 三、严格模式下 arguments 的关键变化

1. 与形参不再“绑定”(解耦)

这是最重要的区别!

非严格模式(怪异行为):
function f(a) {a = 10;console.log(arguments[0]); // 10(同步修改!)
}
f(5);
严格模式(行为正常):
'use strict';
function f(a) {a = 10;console.log(arguments[0]); // 5(不再同步!)
}
f(5);

优点:避免了令人困惑的隐式副作用,使代码更可预测。


2. arguments.callee 和 arguments.caller 被禁用

'use strict';
function f() {console.log(arguments.callee); // ❌ TypeError!
}

这两个属性在严格模式下访问会直接抛出错误。

arguments 本身的其他功能(如 arguments[0], arguments.length)完全正常


3. arguments 仍然是类数组对象

  • 依然不是真正的数组(即使在严格模式下)。
  • 仍然需要转换才能使用数组方法:
    'use strict';
    function f() {const args = Array.from(arguments);// 或 [...arguments](但注意:严格模式下不能在箭头函数中用 arguments)
    }

arguments.callee ?

  • arguments.callee 指向当前正在执行的函数对象
  • 它存在于 arguments 对象上(仅限非箭头函数)。

示例(传统用法):

// 匿名函数递归(ES3/ES5 常见写法)
var factorial = function(n) {if (n <= 1) return 1;return n * arguments.callee(n - 1); // 调用自身
};console.log(factorial(5)); // 120

在这个例子中,因为函数是匿名的,无法通过名字调用自己,所以用 arguments.callee 实现递归。

现在替代方案 :使用命名函数表达式

var factorial = function fact(n) {if (n <= 1) return 1;return n * fact(n - 1); // 通过内部名字调用
};console.log(factorial(5)); // 120

即使外部变量名被修改,fact 在函数内部依然有效。

arguments.caller

  • arguments.caller 是 arguments 对象上的一个属性。
  • 理论上,它应返回调用当前函数的那个函数(即“调用者”)。
  • 仅存在于非严格模式非箭头函数中。

示例:

function callerFunc() {calleeFunc();
}function calleeFunc() {console.log(arguments.caller); // 期望输出 callerFunc
}callerFunc();

但在实际中,这个属性的行为极不稳定,且在多数现代引擎中已被移除或设为 null/undefined

除了 arguments.caller,还有一个类似的属性:Function.caller(函数对象自身的属性)。

function f() {console.log(f.caller); // 调用 f 的函数
}
  • 同样被废弃。
  • 同样在严格模式下访问会报错。
  • 行为同样不可靠。

如果确实需要知道“谁调用了我”,应通过参数显式传递:

function handleAction(callerName, data) {console.log(`${callerName} triggered action with`, data);
}function buttonClick() {handleAction('buttonClick', { id: 1 });
}

六、函数对象的 .length 属性

基本用法

function foo(a, b, c) {// ...
}console.log(foo.length); // 输出: 3

⚠️ 注意:.length 返回的是函数声明中命名参数的个数不包括

  • 剩余参数(...args
  • 默认参数(从第一个有默认值的参数开始,后面的参数不计入)
  • 解构参数(某些情况下可能为 0)

📌 规则详解(ES6+)

根据 ECMAScript 规范,函数的 .length 是这样确定的:

1. 普通参数
function f(a, b) {}
console.log(f.length); // 2
2. 剩余参数(Rest Parameters)不计入
function f(a, b, ...rest) {}
console.log(f.length); // 2(...rest 不算)
3. 默认参数:从第一个带默认值的参数开始,之后的都不计入
function f(a, b = 1, c) {}
console.log(f.length); // 1(b 有默认值,b 和 c 都不算)function f(a, b, c = 1) {}
console.log(f.length); // 2(只有 c 有默认值,所以 a、b 计入)function f(a = 1, b, c) {}
console.log(f.length); // 0(a 有默认值,后面全部不算)
4. 解构参数:通常 .length 为 0
function f({ name, age }) {}
console.log(f.length); // 0function f([x, y]) {}
console.log(f.length); // 0

即使解构中有默认值,也一样:

function f({ name = 'Alice' } = {}) {}
console.log(f.length); // 0
5. 箭头函数同样适用
const f = (a, b, c) => {};
console.log(f.length); // 3const g = (a, b = 1) => {};
console.log(g.length); // 1
6. 类构造函数
class MyClass {constructor(a, b) {}
}
console.log(MyClass.length); // 2

❌ 不能获取“实际调用时传入的参数个数”

函数的 .length静态的,只反映声明时的形参设计,不是运行时传入的实参个数。

要获取调用时实际传入的参数个数,需在函数内部使用:

  • arguments.length(非箭头函数)
  • 或通过 剩余参数 ...args 的长度
function f() {console.log('声明参数个数:', f.length);        // 0console.log('实际传入个数:', arguments.length); // 运行时决定
}f(1, 2, 3);
// 输出:
// 声明参数个数: 0
// 实际传入个数: 3

箭头函数没有 arguments,只能用 ...args

const f = (...args) => {console.log('实际传入个数:', args.length);
};

七、更现代的剩余参数

ES6 的设计哲学之一是让常见操作更简洁、更符合直觉。剩余参数做到了:

✅ 显式声明可变参数

function log(first, ...rest) {console.log('First:', first);console.log('Others:', rest); // rest 是真正的数组
}
  • 从函数签名即可看出参数结构。
  • 代码自文档化(self-documenting)。
✅ 原生支持数组方法
function sum(...numbers) {return numbers.reduce((a, b) => a + b, 0); // 直接调用 reduce
}
✅ 与解构赋值风格统一

剩余参数语法 ... 与**扩展运算符(Spread Operator)**共享相同符号,形成对称设计:

  • Rest(收集)function f(...args) → 把多个参数“收集”成数组。
  • Spread(展开)f(...array) → 把数组“展开”为参数。

这种对称性提升了语言的一致性和表达力。


提升工具链和类型系统的友好性

  • 静态分析更简单:工具(如 ESLint、Babel、TypeScript)能更容易理解 ...args 的意图。
  • TypeScript 类型推断更准确
    function f(...args: number[]) { /* args 类型明确 */ }
    而 arguments 在 TS 中类型复杂且不直观。

推动函数式编程风格

剩余参数天然支持高阶函数无参数数量限制的组合函数

const pipe = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value);

这种写法在函数式编程中非常常见,而 arguments 会让代码变得笨重。


与模块化和现代 API 设计兼容

现代 JavaScript 强调明确性可预测性。剩余参数让函数接口更清晰,便于:

  • 编写文档
  • 单元测试(明确知道哪些是固定参数,哪些是可变参数)
  • 构建灵活的 API(如 console.log(...items)

总结:ES6 引入剩余参数的核心动机

问题(ES5 时代)ES6 解决方案
arguments 不是数组...args 是真正的数组
语法隐式、不直观显式声明,语义清晰
与形参绑定行为怪异无绑定,行为可预测
不支持箭头函数全函数类型通用
与语言其他特性割裂与扩展运算符、解构等统一设计

💡 剩余参数不是为了“替代”arguments 而存在,而是为了解决 JavaScript 在可变参数处理上的设计缺陷,使语言更简洁、安全、一致。

如今,在新代码中应始终优先使用 ...args,仅在维护旧代码或特殊场景下才考虑 arguments

http://www.dtcms.com/a/475609.html

相关文章:

  • 免费网站建设c3sales给帅哥做奴视频网站地址
  • 中英文外贸网站源码代做效果图网站哪家好
  • 【Swift】LeetCode 15. 三数之和
  • 做网站表格单边框标记南通建设局网站查询
  • 百度正版下载恢复百度莱阳seo排名
  • 利用AI工具生成毕业论文,并智能管理相关文献资源。
  • erp网站建设方案asp自动获取网站快照 网站缩略图
  • 做网站为什么要备案照相石家庄网站排名推广
  • 机器学习实践项目(一)- Rossman商店销售预测 - 模型训练
  • 200M电信宽带做网站济南品牌网站建设价格低
  • 没后台的网站怎么做优化博物馆设计公司排名
  • 西部数码域名备案seo技术导航
  • 做的网站没有手机版网站如何推广好
  • 用网站做淘宝客的人多吗会员管理系统免费版
  • 网站建设仟首选金手指制作企业网站的新闻
  • 上海网站建设百度推广公司哪家好wordpress文章在哪
  • 重庆云诚度网站建设关键词排名优化教程
  • seo移动网站页面怎么做怎么在网站里做网页
  • 公司网站建设为什么不直接买模版h5招聘模板免费
  • 360搜索怎么做网站优化seo一个关键词多少钱
  • 开平市城乡建设局网站搜索引擎营销的主要方法包括
  • 类与对象 -- 日期类实现
  • 网站一键生成wapwordpress模板安装
  • 新能源网站建设哪家好门户网站建设要多少钱
  • 网站风格 颜色搭配美橙网站建设经典案例
  • 网站功能建设特点广西壮族自治区市场监督管理局
  • 【Bean】条件装配与动态注册
  • 做厨具公司网站广州开发网站
  • 网站建设编程时注意事项网站设计开发制作
  • Python datetime 教程