当你尝试修改它时,为什么javascript参数对象表现得如此奇怪?

时间:2015-07-01 13:51:58

标签: javascript arguments

考虑以下事项:

foo打算获取参数对象并重新排列顺序,将arg1移动到arg2的位置

function foo (args) {
    args[2] = args[1];
    args[1] = undefined;
}

bar用它的参数调用foo

function bar (a, b, c) {
    foo(arguments);
    console.log(arguments);
}

我希望以下结果类似于{ 0: 'hello', 1: undefined, 2: 'world' }

bar('hello', 'world');

然而,我得到:

{
    0: 'hello',
    1: undefined,
    2: 'world',
    3: undefined,
    4: undefined,
    5: undefined,
    6: undefined,
    7: undefined,
    8: undefined,
    9: undefined,
    10: undefined,
    11: undefined,
    12: undefined,
    13: undefined,
    14: undefined,
    15: undefined,
    16: undefined,
    17: undefined,
    18: undefined,
    19: undefined
}

我完全不知道为什么会这样。 有人有什么想法吗?

我在node.js环境中运行它

1 个答案:

答案 0 :(得分:3)

arguments object不是数组。它是一个内部类型为Arguments的列表,其中包含length属性以及属性0len - 1的getter / setter,其中len是较小的length函数的声明参数数量和调用函数的元素数量。创建此对象后,系统在操作其属性时不会增加/减少length,并且尝试将其设置为0不会添加/删除密钥。属性len - 1b = 1的getter / setter确实是函数中参数名称的别名(即,当您设置arguments[1] === 1时,您将看到foo)。

args[2]尝试设置Arguments时发生的事情是添加一个整数属性会触发V8将底层数组存储大小调整为20个元素(它应该知道这是一个args[20] = 1输入所以它可能会将其设置为哈希属性而不是)。如果您设置args[100] = 1它将调整为47,args[1026] = 1将调整为167,但设置args[1025] = 1将使其成为稀疏数组(但首先设置args[2048]然后{ {1}}不会使它稀疏)等等。

调整大小后,Object.keys会将所有0报告为19作为属性,因此console.log(调用util.format)只打印所有这些属性。

(function (a, b, c) { (function (args) { args[2] = 1; })(arguments); console.log(Object.keys(arguments)); })("hello", "world")

["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"]

这绝对是一个V8错误,虽然它非常前卫。