Good question!
The Array constructor function (with can be used without new), when passed more than 1 argument, creates an array containing the arguments passed in as its elements. So you can do this:
Array(1, 2, 3); // => [1, 2, 3]
As you probably know, Function.prototype.apply allows you to provide arguments to a function in the form of an array. So calling Array.apply (which just inherits its .apply() method from Function’s prototype; any function that is an instance of Function would allows you to do this), which will be functionality equivalent to the code above:
Array.apply(null, [1, 2, 3]); // => [1, 2, 3]
Now, here’s why things are a bit confusing. The Array.prototype.map method is spec’d in such a way that it deals with sparse arrays specially. A sparse array is one that has a “length” that is greater than the number of elements that have actually been inserted. For example:
var arr = [];
arr[0] = 'foo';
arr[5] = 'bar';
The array constructed above will have a length property of 6, because it has an element at index 0 and one at index 5. However, since no elements were ever inserted between those indices, if you call map on it you’ll see that the mapping function does not get applied to the missing elements:
// This should throw, right? Since elements 1 through 4 are undefined?
var lengths = arr.map(function(s) { return s.length; });
// Nope!
lengths; // => [3, , , , , 3]
And why are we seeing this behavior in your example with new Array(5)? You guessed it: because the array constructor, when given a single argument, creates a sparse array with the specified length.
So the issue here is that while map (and other methods on Array.prototype, such as forEach) behaves specially with respect to sparse arrays by skipping over the missing values, the Function.prototype.apply method does not have any such special behavior.