In an array literal, a comma at the end is ignored, but all the other commas delimit elements. If you omit the value of an element, it defaults to undefined, but the element is still there. So
[,]
is equivalent to
[undefined,]
which is equivalent to
[undefined]
This has 1 element whose value is undefined.
Similarly
[,,] = [undefined, undefined, ] = [undefined, undefined]
which has 2 elements.
The default element behavior is more useful when you want to omit elements in the middle of an array.
[1, 2, 3, , , 6, 7, 8]
Actually, there's a small difference between the two ways of creating undefined elements. In Javascript, an array is actually an object that has a length property and properties whose names are the indexes of the array elements. Normally, if an array has length = N, the index properties will be all the integers from 0 to N-1. But when you omit an element in the array literal, no property is created for that index.
For most purposes, this missing property is not significant, because accessing a nonexistent property of an object returns undefined, just as if you have a property whose value is undefined. You can only detect these missing properties by using a method like hasOwnProperty or calling Object.keys. The Javascript console uses something like this to display gaps in the array differently from explicit undefined elements.
So
Object.getOwnPropertyNames([1, 2, 3]) => ["0", "1", "2", "length"]
Object.getOwnPropertyNames([1, , 3, 4]) => ["0", "2", "3", "length"]
Object.getOwnPropertyNames([, , , , ]) => ["length"]
The reason for ignoring the last comma is so you can write:
[ 
    "foo",
    "bar",
    "baz",
    "quux",
]
This makes editing easier, because you can insert and delete lines without having to special-case the last element.