impressed you managed to phrase my question better than I could, you are indeed correct as on reflection all I need is an array of numbers that I can later loop through :) Thanks for your answer.
– GoddersSep 19 '10 at 18:08

108

@Godders: If this is what you're looking for, why do you need an array? A simple var n = 45; and then looping from 1..n would do.
– casablancaSep 19 '10 at 18:33

3

@Godders - To note, if you want to decrease the size of the array after it is created to length M, simply use foo.length = M --- The cut off info is lost. See it in action ==> jsfiddle.net/ACMXp
– Peter AjtaiSep 20 '10 at 2:11

15

I really dont get why this answer even have upvotes... especially when the OP himself agrees it doesn't make any sense in a few comments above since he could just have done var n = 45;.
– plalxNov 4 '13 at 14:39

49

@scunliffe: Please note, that new Array(45); does not "create a 45 element array" (in same meaning as [undefined,undefined,..undefined] does). It rather "creates empty array with length = 45" ([undefined x 45]), same as var foo = []; foo.length=45;. That's why forEach, and map will not apply in this case.
– tomalecJan 24 '14 at 14:00

Since ECMAScript 5, Function.prototype.apply(thisArg, argsArray) also accepts a duck-typed array-like object as its second parameter. If we invoke Array.apply(null, { length: N }), then it will execute

Now we have an N-element array, with each element set to undefined. When we call .map(callback, thisArg) on it, each element will be set to the result of callback.call(thisArg, element, index, array). Therefore, [undefined, undefined, …, undefined].map(Number.call, Number) would map each element to (Number.call).call(Number, undefined, index, array), which is the same as Number.call(undefined, index, array), which, as we observed earlier, evaluates to index. That completes the array whose elements are the same as their index.

Why go through the trouble of Array.apply(null, {length: N}) instead of just Array(N)? After all, both expressions would result an an N-element array of undefined elements. The difference is that in the former expression, each element is explicitly set to undefined, whereas in the latter, each element was never set. According to the documentation of .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.

Therefore, Array(N) is insufficient; Array(N).map(Number.call, Number) would result in an uninitialized array of length N.

Compatibility

Since this technique relies on behaviour of Function.prototype.apply() specified in ECMAScript 5, it will not work in pre-ECMAScript 5 browsers such as Chrome 14 and Internet Explorer 9.

Very clever -- probably too so. Exploiting the fact that Function.prototype.call's first param is the this object to map directly over Array.prototype.map's iterator parameter has a certain brilliance to it.
– Noah FreitasAug 17 '14 at 22:46

+1 because it's a whole big O better than the nasty .join.splitversion - but I still think the humble loop is better.
– RobinApr 24 '16 at 19:33

I agree @Robin - Algorithmic complexity aside, the humble loop is always more readable. However, with the advent of lambdas in Java, I think map will soon become a standard for things like this.
– NateApr 24 '16 at 19:37

I don't understand why .fill() is necessary. I see that it is when I test on node's repl, but since Array(1)[0] === undefined, what difference does the call to fill() in Array(1).fill(undefined) make?
– DominicOct 14 '16 at 9:45

9

For anyone else who is interested, the difference between Array(N) and Array(N).fill() is explained well here
– DominicOct 17 '16 at 8:59

I know your question is asking to populate an array numerically, but I'm uncertain why you'd want to do this.

Arrays innately manage their lengths. As they are traversed, their indexes can be held in memory and referenced at that point. If a random index needs to be known, the indexOf method can be used.

This said, for your needs you may just want to declare an array of a certain size:

var foo = new Array(N); // where N is a positive integer
/* this will create an array of size, N, primarily for memory allocation,
but does not create any defined values
foo.length // size of Array
foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array
*/

ES6

Spread

Making use of the spread operator (...) and keys method, enables you to create a temporary array of size N to produce the indexes, and then a new array that can be assigned to your variable:

var foo = [ ...Array(N).keys() ];

Fill/Map

You can first create the size of the array you need, fill it with undefined and then create a new array using map, which sets each element to the index.

var foo = Array(N).fill().map((v,i)=>i);

Array.from

This should be initializing to length of size N and populating the array in one pass.

I believe this is useful when the array of numbers is being used for data that cannot be processed at the receiving end. (Like an HTML template that is just replacing values.)
– Neil MonroeAug 22 '12 at 15:01

Why someone would do this is to have an array of numbers to populate a dropdown list, giving the user a choice from 1 to 10. A small array by hand [1,2,3...10] make sense, but what if it's from 1 to 50? What if the end number changes?
– CigarDougOct 23 '18 at 20:33

@CigarDoug I don’t doubt there is a usecase, but my guess it is small. Why would an array of numbers be needed, usually when iterating over an array an index would be used as part of the loop construct — either as an argument to the looping body function, or a counter variable — so holding the array of numbers seems trivial to just creating an array of specified width, or just a variable that holds the upper bound of the array. I can think of a few use cases, but none of those had been expressed by the OP
– vol7ronOct 23 '18 at 21:19

1

Like I said, I need to populate a dropdown with the numbers 1 through 10. That's all. There IS a usecase, MY usecase. That's how I found this page. So just building an array by hand was less complicated than anything I saw here. So my requirements aren't the requirements of the OP. But I have my answer.
– CigarDougOct 24 '18 at 11:24

I’m not sure I fully understand your predicament, but IMHO that would be a poor usecase, leading to slow and confusing code. I’d say the OP shows a better way of doing that than using a loop, which is what I’d recommend for that case. The reasons for pre-populating a serial array are very limited and not worth expressing here as it’d be a minute probability that SO users would require it and those that would are so skilled they wouldn’t need to ask or research the question.
– vol7ronOct 24 '18 at 12:18

I like this. If you wanted to go the extra mile with it, you could declare it as Array.prototype.range = function(start, end) { ... };. Then, you can call range(x, y) on any Array object.
– Zach RattnerSep 19 '10 at 17:44

8

Rather make it a method of Array instead of Array.prototype as there is no reason (it might even be considered rather dumb) to have this method on every array.
– adamseSep 19 '10 at 17:47

9

Array.range(1, 5) would probably be more appropriate, but there is something kind of cool about writing [].range(1, 5).
– MooGooSep 19 '10 at 17:54

"Rather make it a method of Array instead of Array.prototype" - What's the difference? You mean on a specific array only?
– pilauApr 11 '13 at 13:32

3

@pilau Just as adamse says, it looks weird. If it's on the prototype, you can say foo = [1, 2, 3]; bar = foo.range(0, 10);. But that's just...confusing. bar = Array.range(0, 10) is a lot more clear and explicit. The range has nothing to do with the instance, so there's no reason to make it an instance method.
– Ian HenryApr 11 '13 at 14:19

This is an interesting solution but it's entirely impractical - having to parse the array 3 times (once to join, once to split, and once for the thing you actually want to do) is just not nice - I know they seem to have fallen out of favor for some reason, but it would be far better to simply use a good old fashioned loop!
– RobinApr 24 '16 at 19:29

For some reason this solution dosen't works in the Production Version from Expo (react-native) App. [...Array(N + 1).keys()] this code returns a empty array, but just in the production mode, using the development mode works.
– FabianoLothorJun 2 '18 at 5:28

1

The .keys() answer was already given years ago and has 500+ upvotes. What does your answer add to it?
– Dan DascalescuSep 13 '18 at 23:13

FYI: As John Reisig first published a few years ago - on some platforms (meaning windows:P) time is being fed to the browser once every 16ms. Also there are other problems with measuring time of execution in multitasking environments. jsperf.com has implemented running the tests so that they are statistically correct. It's ok to run console.time() to get an intuition, but for a proof, you need jsperf.com AND it shows you cross-browser results from other people (different hardware etc)
– naugturSep 14 '13 at 8:58

@cocco— while isn't always faster than other loops. In some browsers, a decrementing while loop is much slower than a for loop, you can't make general statements about javascript performance like that because there are so many implementations with so many different optimisations. However, in general I like your approach. ;-)
– RobGAug 9 '15 at 23:57

Creates an array of numbers
(positive and/or negative) progressing from start up to, but not
including, end. A step of -1 is used if a negative start is specified
without an end or step. If end is not specified, it's set to start
with start then set to 0.

This is the shortest code to generate an Array of size N (here 10) without using ES6. Cocco's version above is close but not the shortest.

(function(n){for(a=[];n--;a[n]=n+1);return a})(10)

But the undisputed winner of this Code golf(competition to solve a particular problem in the fewest bytes of source code) is Niko Ruotsalainen . Using Array Constructor and ES6 spread operator . (Most of the ES6 syntax is valid typeScript, but following is not. So be judicious while using it)

There is another way in ES6, using Array.from which takes 2 arguments, the first is an arrayLike (in this case an object with length property), and the second is a mapping function (in this case we map the item to its index)

Array.from({length:10}, (v,i) => i)

this is shorter and can be used for other sequences like generating even numbers

Array.from({length:10}, (v,i) => i*2)

Also this has better performance than most other ways because it only loops once through the array.
Check the snippit for some comparisons

Similarly, you can also do the following in ES6: Array.from({length: N}, (v, k) => k).
– XåpplI'-I0llwlg'I -Jun 8 '15 at 9:19

Xappli's approach is preferred: Array.from was created for almost this exact scenario, and it implies a mapping callback. It's an excellent solution to the general problem of wanting to use Array methods on something array-like, without resorting to verbose approaches like Array.prototype.map.call, e.g. for NodeLists returned from document.querySelectorAll. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
– Josh from QaribouOct 16 '15 at 2:50

Technically it's not Array.from which turns the sparse values into undefined. Rather Array(5) is called as an arguments object which in turn interprets the sparse values as undefined values :)
– CervEdOct 22 '16 at 11:21

That's a seriously inefficient approach. It creates 3 arrays, a string, and calls a function max - min times. Consider: for (var i=max-min+1, a=[]; i--;) a[i] = min+i; which creates one array and does one loop and is less to write. ;-)
– RobGAug 9 '15 at 23:54

Object.keys(new Int8Array(N)) is a clever hack, and faster than the Array.apply() and Array.from() solutions, but with ES2015, we have a faster and less weird-looking solution, [...Array(11).keys()].slice(1).
– Dan DascalescuSep 13 '18 at 23:31

Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).