While answering this question ( Difference between [Object, Object] and Array(2) ) I happened across something in JavaScript arrays that I wasn't previously aware of (ironic, considering I worked on Arrays in the Chakra engine while at Microsoft).
If I enter this into Chrome's JavaScript console...
var x = Array(2);
var y = [undefined, undefined];
var z = [,];
...then when query the x
, y
and z
variables I get this output respectively:
> x
< [undefined × 2]
< length: 2
> y
< [undefined, undefined] (
< 0: undefined
< 1: undefined
< length: 2
> z
< [undefined × 1]
< length: 1
MDN's relevant documentation for Array(arrayLength)
and the []
literal syntax states:
If the only argument passed to the Array constructor is an integer this returns a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength
empty slots, not slots with actual undefined values). If the argument is any other number, a RangeError
exception is thrown.
I note that the documentation does not further explicate on the concept of a "slot" - I assume they're using it as a synonym for "array element" (I'm aware that JavaScript arrays can be sparse-arrays that have a different internal representation, but that shouldn't affect how consumers see them - given that JavaScript arrays and objects are abstractions over a variety of data structures anyway).
The documentation on MSDN for the same does not provide any mention of edge-case arguments for the Array
function or Array-literal []
syntax.
So my questions are:
- What does
undefined × 2
mean?
- Why does
Array(2)
evaluate to [undefined × 2]
instead of [undefined, undefined]
?
- Why does
[,]
have a length: 1
?
To attempt to answer my own questions I consulted the ECMA-262 7.0 specification on Array Literals. There's an interesting note on elided array literal elements (emphasis mine):
Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by an AssignmentExpression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the Array and increases the index of subsequent elements. Elided array elements are not defined. If an element is elided at the end of an array, that element does not contribute to the length of the Array.
So the part in bold answers my third question, at least: if the last element is "missing" then it does not exist, and if a non-terminal element doesn't have a value then it's undefined
. So these expressions are equivalent:
[a,] --> [a]
[a,b,] --> [a,b]
[a,,b] --> [a,undefined,b]
Therefore
[,] --> [undefined]
[,,] --> [undefined,undefined]
So I tried this in Chrome:
> var a = [,,];
> a
> [undefined × 2]
> length: 2
This is unexpected! I thought [,,]
to be equivalent to [undefined,undefined]
as per the explicit rules of element elision, yet Chrome considers [,,]
to be equivalent to Array(2)
instead (note there are no indexers defined, giving it the same result as case y
).
So my forth question:
- Why is
[,,]
equivalent to Array(2)
but not [undefined,undefined]
?
See Question&Answers more detail:
os