Create an Array with n values that is able to use Array methods instantly

As it is impossible to use Array methods on new Array(n), e.g. new Array(5).map(/* [some callback] */), I deviced a pseudo static Array method.

The idea is to call an anonymous function that fills an empty Array with n times the value undefined. In its simplest form it returns an Array for which Array-methods are applicable.

If you supply parameters (a callback method (Function), the method identifier itself (String, default = 'map') and optionally an initial value, the callback method mapCB is applied to the (Array)method, and the resulting Array is returned.

It looks like this:

window.addEventListener('load', function () {
Array.create = function (n, mapCB, method, initial) {
method = method in [] ? method : 'map';
var nwArr = ( function (nn){
while (nn--)
this.push(undefined);
return this; } )
.call([],n);
return mapCB ? nwArr[method](mapCB, initial) : nwArr;
};
// usage examples
var someArr0 = Array.create(100).map(function (v, i) {return i;});
var someArr1 = Array.create(100, function (v, i) {return this + i;}, 'map', 5);
var someArr2 = Array.create(100, function (p, n, i) {return p+i;}, 'reduce', 0);
Helper.log2Screen('someArr0: [ <code>',someArr0.join(', '),'</code> ]');
Helper.log2Screen('someArr1: [ <code>',someArr1.join(', '),'</code> ]');
Helper.log2Screen('someArr2: <code>',someArr2,'</code>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://www.nicon.nl/genericsvc/fiddle/fiddlemeta.js"></script>

Do you think it's useful, or are there better way to achieve this?

I'm aware of the Array.apply(undefined, Array(n)) to create a usable Array, but that will run into a maximum call stack error at some point with a large n used.

    function createArrayWithNElements(nElements, defaultValue) {
var arr = [];
for (var i=0; i < nElements; i+=1) {
arr.push(defaultValue);
};
return arr;
}
function createArrayWithNElementsAndApplyMethod(n, methodObj) {
var arr = createArrayWithNElements(n);
return arr[methodObj.method](methodObj.callback, methodObj.initialValue);
}
Array.create = createArrayWithNElements;
Array.createAndApply = createArrayWithNElementsAndApplyMethod;
// usage examples
Array.create( 10, 0 ); //=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Array.createAndApply( 10, { method:'map',
callback: function (v, i) {return this + i;},
initialValue: 5 } );
//=> [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

• Why don't you explain in words what you're trying to accomplish rather than try to make us reverse engineer what you have? – jfriend00 Oct 28 '14 at 10:02
• Myself and a colleague were talking about this the other day when trying to make a repeatString function with new Array(5).join('x');. join() does work on a newly constructed array but we found map() didn't. – Adrian Lynch Oct 28 '14 at 10:12
• @jfriend00: better? – KooiInc Oct 28 '14 at 10:14
• If I ran into any of those last three lines of code in some code I was working on, I would have absolutely no idea what they did and once I found the .create() method somewhere, I'd still not know what they did without a lot of study. I'd much rather see separate named functions that have clear names indicating what they do. This looks cryptic as it tries to overload a single non-descriptive method with a whole bunch of functionality. In my hierarchy of importance, readability and ease of understanding are way more important than brevity and this appears to only be optimizing for brevity. – jfriend00 Oct 28 '14 at 10:21

As the comments already say, I'd not put too much into such a function, that is, IMO creating the array with initial size and elements is probably enough to make a difference.

Array.create = function (n, initial) {
var result = new Array (n);
for (var i = 0; i < n; ++i)
result[i] = initial;
return result;
};

// Array.create (3);
// Array.create (5, "hi").map (...);


Which also could just be a regular function makeArray or so I guess. So you get one benefit without the rather cryptic calling convention (mapCB/method) you have at the moment. Sure, it's a matter of opinion, but I had to take a moment to understand what that is supposed to do, so arguably that is not a good choice if you want other people to read that later.

And good point about the apply, I wouldn't want to see that in real code as well.

• A reasonable extension to this would be instead of passing an initial value to pass a function that accepts the index and lets you return what you want from there. So Array.create(10, identity); //=> [0 .. 9] and Array.create(5, square); //=> [0, 1, 4, 9, 16]. This strikes me as quite useful without getting into the complexity in the original solution. – Scott Sauyet Oct 30 '14 at 18:17