Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

consider the following:

foo intends to take the arguments object and rearrange the order, moving arg1 to the position of arg2

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

bar calls foo with it's arguments

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

I expect the result of the following to be something like { 0: 'hello', 1: undefined, 2: 'world' }

bar('hello', 'world');

However, i get:

{
    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
}

I am at a complete loss as to why this happens. Anyone have any ideas?

I'm running this in a node.js environment

like image 365
StickyCube Avatar asked Jul 01 '15 13:07

StickyCube


People also ask

What could be the purpose of the arguments inside a function in JavaScript?

The arguments is an object which is local to a function. You can think of it as a local variable that is available with all functions by default except arrow functions in JavaScript. This object (arguments) is used to access the parameter passed to a function. It is only available within a function.

What is arguments object in JavaScript?

The arguments object is a local variable available within all non-arrow functions. You can refer to a function's arguments inside that function by using its arguments object. It has entries for each argument the function was called with, with the first entry's index at 0 .

How does argument work in JavaScript?

Arguments are Passed by Value The parameters, in a function call, are the function's arguments. JavaScript arguments are passed by value: The function only gets to know the values, not the argument's locations. If a function changes an argument's value, it does not change the parameter's original value.

What is argument error in JavaScript?

The JavaScript exception "more arguments needed" occurs when there is an error with how a function is called. More arguments need to be provided.


1 Answers

The arguments object is not an array. It is a list with the internal type Arguments, with a length property and getters/setters for properties 0 to len - 1 where len is the lesser of the number of declared arguments of the function and the number of elements you called the function. Once this object is created, the system will not increase/decrease length when you operate on its properties, and attempting to set it a length does not add/remove keys. The getters/setters for properties 0 to len - 1 are indeed aliases to your argument names within the function (i.e., when you set b = 1 you will see arguments[1] === 1).

What's happened when foo tries to set args[2] is addition of an integral property triggers V8 to resize the underlying array storage to 20 elements (it somehow should know that this is an Arguments type so it can probably set it to a hash property instead). If you set args[20] = 1 it will be resized to 47, args[100] = 1 will resize to 167, but setting args[1026] = 1 will make it a sparse array (but first setting args[1025] = 1 and then args[2048] does not make it sparse), etc.

After resized, Object.keys reports all 0 to 19 as properties, so console.log (which calls util.format) just prints all of them.

(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"]

This is definitely a V8 bug, although it is very edgy.

like image 88
Alan Tam Avatar answered Oct 25 '22 15:10

Alan Tam