为什么当您试图修改javascript arguments对象时,它的行为如此奇怪

Why does the javascript arguments object behave so strangely when you try to modify it?

本文关键字:修改 对象 arguments javascript 为什么      更新时间:2023-09-26

考虑以下内容:

foo打算接受arguments对象并重新排列顺序,将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环境中运行这个程序

arguments object不是数组。它是一个内部类型为Arguments的列表,具有length属性和属性0len - 1的getters/ssetters,其中len是函数声明的参数数和调用函数的元素数中的较小者。一旦创建了此对象,当您对其属性进行操作时,系统将不会增加/减少length,并且尝试将其设置为length不会添加/删除键。属性0len - 1的getter/setter实际上是函数中参数名称的别名(即,当您设置b = 1时,您将看到arguments[1] === 1)。

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

调整大小后,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的错误,尽管它非常尖锐。