Arguments
arguments
对象是函数内部的一个特殊对象,它包含了函数调用时传入的所有实参。下面是arguments
对象的一些特点:
arguments
是一个类数组对象,可以通过索引访问其中的元素。arguments
对象是函数内部的局部变量,每个函数都有自己的arguments
对象。arguments
对象是不可迭代的,不能直接使用for...of
循环遍历。- 箭头函数没有自己的
arguments
对象,它会捕获外部函数的arguments
对象。
下面是一个使用arguments
对象的示例:
function test(a, b, c) {
console.log(arguments.toString()); // [object Arguments]
console.log(Array.isArray(arguments)); // false
console.log(arguments.callee); // 打印宿主函数
}
test();
箭头函数的 arguments
箭头函数没有自己的arguments
对象,但可以通过 rest 参数(...args
)来获取传入的实参:
var test1 = (...args) => {
console.log(args); // [1, 2, 3]
};
test1(1, 2, 3);
将 arguments 转换为数组
由于arguments
是一个类数组对象,有时我们需要将其转换为真正的数组。常见的转换方法是使用Array.prototype.slice.call(arguments)
:
function test() {
var argArr = [].slice.call(arguments);
console.log(argArr);
}
test(1, 2, 3); // [1, 2, 3]
但是,使用slice
方法会阻止 JavaScript 引擎对函数进行某些特定的优化。更好的转换方式是根据arguments
的长度进行判断:
function test() {
var argArr = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
console.log(argArr);
}
test(1, 2, 3); // [1, 2, 3]
arguments 的使用场景
arguments
对象常用于处理不定参数或传入参数数量大于形参数量的情况:
function test(a, b, c) {
console.log(arguments[3]);
}
test(1, 2, 3, 4); // 4
arguments 和形参的关系
在非严格模式下,修改arguments
对象的元素会同步更新对应的形参的值,反之亦然。但是,如果形参使用了默认值、解构赋值或者 rest 参数,则arguments
对象不再跟踪参数的值。
function test(a = 100) {
a = 1000;
console.log(a, arguments[0]); // 1000 1
}
test(1);
严格模式下的 arguments
在严格模式下,arguments
对象和形参不再存在同步关系,修改一个不会影响另一个。
function test(a, b, c) {
'use strict';
(a = 10), (b = 20), (c = 30);
console.log(a, b, c); // 10 20 30
console.log(arguments); // [1, 2, 3]
}
test(1, 2, 3);
arguments
对象是 JavaScript 函数中一个独特的存在,它提供了一种访问函数实参的方式。合理使用arguments
对象可以使函数更加灵活和通用,但也要注意避免滥用导致性能问题。在现代 JavaScript 中,越来越多地使用 rest 参数和解构赋值来处理函数参数,减少了对arguments
对象的依赖。