arguments object not an array. This is a list with the internal type Arguments with the property length and getters / setters for the properties 0 to len - 1 , where len is the smallest of the declared arguments of the function and the number of elements that you called the function. After creating this object, the system will not increase / decrease length when working with its properties, and when trying to set its length does not add / remove keys. The getters / setters for the 0 to len - 1 properties are indeed aliases for your argument names inside the function (ie. When you set b = 1 , you will see arguments[1] === 1 ).
What happened when foo tries to set args[2] is the addition of triggers of the V8 integral property to resize the storage of the base array to 20 elements (it somehow needs to know that it is an Arguments type, so it can probably set this instead of a hash -properties). If you set args[20] = 1 , the size 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 set args[1025] = 1 , and then args[2048] will not make it sparse), etc.
After resizing, 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 sharp.