admin管理员组

文章数量:1201793

Lately I started seeing this in firefox' console

Object [ <6 empty slots>, false, <3 empty slots>, 1 more… ]

When I have an object like

{
  6: false,
  10: true
}

I simply want an object with numeric keys that I can access, but I am worried by this because if it keeps track of empty slots then this must mean that some memory is wasted?

Are my concerns valid and if yes what would be a correct way to define such an object?

Lately I started seeing this in firefox' console

Object [ <6 empty slots>, false, <3 empty slots>, 1 more… ]

When I have an object like

{
  6: false,
  10: true
}

I simply want an object with numeric keys that I can access, but I am worried by this because if it keeps track of empty slots then this must mean that some memory is wasted?

Are my concerns valid and if yes what would be a correct way to define such an object?

Share Improve this question asked Jun 13, 2017 at 6:27 php_nub_qqphp_nub_qq 16k22 gold badges81 silver badges148 bronze badges 2
  • And if you do [{6:false, 10:true}] the condensed view outputs Array [ Object[11] ] – Kaiido Commented Jun 13, 2017 at 6:38
  • @Jaromanda X Firefox is strictly following the standards and so its reflected in its console output. Chrome on the other hand is dumbing down for ease of use for user/developer and also ignores many W3C standards. So please explain the reason behind the behavior instead of simply bashing it. There must be good reason for firefox to show the empty elements. In genuine cases, it helps in debugging the issue while helping to find problem with Array. – Harshith J.V. Commented Apr 28, 2020 at 8:50
Add a comment  | 

2 Answers 2

Reset to default 13

The problem might be caused at how Firefox' console.log has interpreted the input object. Somehow, it got evaluated as an array instead of a simple object. Chrome does it right. If you look deeper into how an array is managed in Javascript, you can find the following:

Arrays cannot use strings as element indexes (as in an associative array), but must use integers. Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's object property collection. The array's object properties and list of array elements are separate, and the array's traversal and mutation operations cannot be applied to these named properties. src

A better comprehending for this is to tinker with Array's length property. Especially when you have constructed your array by using []. To add elements to the array, we have to use .push(...). This function uses the length property (check 15.4.4.7 Array.prototype.push). So in short (interactive example is at the bottom)

const arr = []; // length = 0
arr.push('1stEl', '2ndEl', '3thEl'); // length = 3
// this isn't allowed, but you can do this
arr[7] = '7thEl'; // length = 8

You see that the length is now 8 and not 4. The indices 3..6 are reserved, but undefined. Here below is a console output.

[
  "1stEl",
  "2ndEl",
  "3thEl",
  undefined,
  undefined,
  undefined,
  undefined,
  "7thEl"
]

If you use a .push method again, it will place the new element after the '7thEl' element (so on index 8).

To check the keys that is used by this object, we can use Object.keys() on the array. You will get

[
  "0",
  "1",
  "2",
  "7"
]

You see that numeric values are used as keys. Like your object, which is

{
  6: false,
  10: true
}

Using Object.keys on this object gives ["6", "10"]. It has a similar output as the above. So the console.log from firefox has interpret your object as an array, thus displaying it as an array. In order to display the array correctly, it starts (logically seen, need to check the source code yet) at key 0 and ends at key array.length - 1. But the indexes 0,1..5 and 7..9 aren't "defined". Thus it leads to this output

Object [ <6 empty slots>, false, <3 empty slots>, 1 more… ]

I'm not sure if I have to qualify this as a bug or glitch at Firefox's console API... Or that the console input (when initializing a variable) has read the object incorrectly.

--- live example --

const a = new Array(3);
console.log('using "new Array(...)" reserves memory space: ' + a.length);
console.log('---');

// using brackets
const b = [];
console.log('but what with [] ? At initial, we have ' + b.length);
b.push('1stEl', '2ndEl', '3thEl');
console.log('After push(\'1stEl\', \'2ndEl\', \'3thEl\'), we have ' + b.length);
// add to random index
b[7] = '7thEl';
console.log('After b[7] = \'7thEl\', we have ' + b.length);

console.log('displaying gives ', b);
console.log('using Object.keys: ', Object.keys(b));

// adding again
b.push('newEl');
console.log('After b.push(\'newEl\'), we have ' + b.length);

// object 
const obj = {
  6: false,
  10: true
};
console.log('obj defined as {6: false, 10: true }');
console.log('using Object.keys: ', Object.keys(obj));
console.log('obj: ', obj);

Javascript uses sparse arrays. "Since an array's length can change at any time, and data can be stored at non-contiguous locations in the array, JavaScript arrays are not guaranteed to be dense; this depends on how the programmer chooses to use them." (source)

If the objects are of type Array, then the memory used is an implementation detail of the engine. In your case, the objects are objects, so it only takes the memory for the object itself, and to store the property names and references to property values.

本文标签: Empty slots in JavaScript objectsStack Overflow