一道面试题引发的问题

78 阅读1分钟

话不多说,先上面试题,如下:

function b(x, y, a) {
  a = 8;
  arguments[2] = 10;
  console.log(a);
}
b(1, 2, 3);

大胆的我,直接就写会输出8。 1.png 然后就被质疑了一顿。 面试结束之后一段时间百度发现。 arguments对象很厉害,修改arguments会影响到函数的形参。如果进行删除arguments某一个参数,函数的形参也会进行变化,比如下面:

function b(x, y, a) {
  a = 8;
  console.log(arguments); // [1, 2, 8]
  arguments[2] = 10;
  console.log("-----------");
  console.log(arguments); // [1, 2, 10]
  console.log(a); // 10
  // 删除
  [].shift.call(arguments); // 删除arguments第一个参数
  console.log("-----------");
  console.log(arguments); // [2, 10]
  console.log(x, y, a); // 2, 10, 10
  // 修改arguments第二个参数
  arguments[1] = 20
  console.log("-----------");
  console.log(arguments); // [2, 20]
  console.log(x, y, a); // 2, 20, 10
  // 新增两个元素
  arguments[2] = 22
  arguments[3] = 33
  arguments.length = 4
  console.log("-----------");
  console.log(arguments); // [2, 20, 22, 33]
  console.log(x, y, a); // 2, 20, 10
}
b(1, 2, 3);

由上面代码可以看出。再修改arguments的时候,形参的值也会修改。第一次删除数据的时候,函数最后一个形参的值直接变成arguments最后一个的值,而且后面修改跟添加都不会影响最后一个形参的值。

建议不要直接修改arguments,需要的话可以是用[].slice.call(arguments)创建新的数组然后进行修改。

关于arguments arguments是一个类数组的对象,要是用数组的方法需要 [].shift.call(arguments)来操作。 arguments还有callee,它的值是当前执行函数,可以用来函数进行内部递归。

function a (index) {
	arguments[0]--
  if (arguments[0] <= 0) {
    return arguments[0]
  } else {
    arguments.callee(index)
    // ...other code
  }
}
a(10)

总结

  • arguments的修改,函数形参的值也会修改;
  • 不要直接修改arguments,会造成想不到的bug; 如果有补充或者错误的,请不吝指点~