(new Array(10)).map(function() { return 1;}) returns [, , , , , ...] ... Why? [duplicate]
I would expect the following code to return [1,1,1,1...]
(new Array(10)).map(function() { return 1;})
but it returns [, , , , , ...]
.
Moreover,
(new Array(10)).length == 10
and (new Array(10))[0] == undefined
are true.
And for z = function(){return 0;};
the expression z(undefined) === 0
is also true.
Yet I have noticed that [,,,,,,,,,,].map(function() { return 1; })
also returns [,,,,....]
.
Can anyone explain why?
Solution 1:
So. I would expect the following code to return [1,1,1,1...].
(new Array(10)).map(function() { return 1;})
But it returns [, , , , , ...].
Right, because new Array(10)
creates an array with no elements with a length
of 10, and map
only iterates over elements that actually exist. (And yes, this is surprising. :-) )
Moreover,
(new Array(10)).length == 10
and(new Array(10))[0] == undefined
aretrue
.
Again correct, because (again) new Array(10)
doesn't put any elements in the array, so accessing [0]
gives you undefined
.
JavaScript's standard arrays aren't really arrays at all, and they can have a length
that's a positive number without having any entries in them. They're a form of "sparse" array.
Let's take a simpler example:
var a = new Array(10);
a[2] = 1;
That array contains one element, the element at index 2
. There is no element at index 0
, no element at index 1
, and no elements at indexes 3
and above. It just has gaps there. You can tell by asking it:
console.log(0 in a); // "false"
console.log(1 in a); // "false"
console.log(2 in a); // "true"
Standard arrays in JavaScript are just objects with special behavior assigned to length
, special behavior assigned to a class of property names (loosely, numeric ones), and that are backed by Array.prototype
.
This is all in contrast to the newer "typed" arrays, Int32Array
and such, which are true arrays in the traditional sense.
Solution 2:
This will work:
Array.apply(null, Array(10)).map(…
Live demo: http://jsfiddle.net/xXG5p/
You have to make the array dense first. new Array(n)
creates a sparse array. Sparse arrays do have a length
but they have no elements. Hence, a .map()
call will not iterate at all.
Using my code above, you will create a dense array that does contain elements (whose values are initially set to null
).
Solution 3:
Here is what the Mozilla Developer Network says about Array.prototype.map:
callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
When you call new Array(10)
, the Array
you create believes it is 10-element long but none of its indexes have ever been assigned to. Here's an example of what happens if you use a literal array for which you have not set values for some indices:
[1, , 3].map(function () {return "a"})
The value you get is:
[ 'a', , 'a' ]
Because at index 1, no value was assigned.