跳到主要内容

Arguments

arguments对象是函数内部的一个特殊对象,它包含了函数调用时传入的所有实参。下面是arguments对象的一些特点:

  1. arguments是一个类数组对象,可以通过索引访问其中的元素。
  2. arguments对象是函数内部的局部变量,每个函数都有自己的arguments对象。
  3. arguments对象是不可迭代的,不能直接使用for...of循环遍历。
  4. 箭头函数没有自己的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对象的依赖。