Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do Array literals with commas but no elements not have a length of 0? [duplicate]

Tags:

javascript

I was just fiddling with some JS and found something I thought would not happen.

var arr = [,];
arr.length // 1
arr[0] // undefined

Moreover, [,,] has a length of 2. Shouldn't these arrays have lengths of 0? I thought commas were only used to separate elements in an array, so why does it appear that commas are counted as elements in these particular arrays? Does this kind of behavior with arrays have any sort of application?

like image 446
sdfsdf Avatar asked Apr 01 '16 01:04

sdfsdf


People also ask

Are trailing commas forbidden in JSON?

As JSON is based on JavaScript's syntax prior to ES5, trailing commas are not allowed in JSON.

What does trailing comma mean?

A trailing comma, also known as a dangling or terminal comma, is a comma symbol that is typed after the last item of a list of elements. Since the introduction of the JavaScript language, trailing commas have been legal in array literals. Later, object literals joined arrays.

How can you create an array in JavaScript using array literal?

Creating an Array Using an array literal is the easiest way to create a JavaScript Array. Syntax: const array_name = [item1, item2, ...]; It is a common practice to declare arrays with the const keyword.

How will you get the second element of the array?

To get the second to last element in an array, call the at() method on the array, passing it -2 as a parameter, e.g. arr.at(-2) . The at method returns the array element at the specified index.


2 Answers

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.

like image 102
Barmar Avatar answered Oct 15 '22 09:10

Barmar


That's called elision. It creates a "hole" in the array (a sparse array). There are probably applications I don't know about and have forgotten about, the only one I can think of right now is the one I show here: https://stackoverflow.com/a/29629588/1034448.

[,...Array(10)].map((x, i) => { /* range of `i` is 1 - 10 */ })

[,,] is not equivalent to [undefined, undefined,]. There is a big difference: iteration methods will not include elements at the elided indexes. Example:

var enumerated = [];

function callback (x, i) {
  enumerated.push(i);
}

[,,].forEach(callback);
console.log(enumerated); // logs []

[undefined, undefined,].forEach(callback);
console.log(enumerated); // logs [1, 2]
like image 21
JMM Avatar answered Oct 15 '22 11:10

JMM