147

I ran this code and got the below result. I curious to know why [] is faster?

console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')

console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
  • using []: 299ms
  • using new: 363ms

Thanks to Raynos here is a benchmark of this code and some more possible way to define a variable.

enter image description here

Community
  • 1
  • 1
Mohsen
  • 64,437
  • 34
  • 159
  • 186
  • 5
    You might be interested in [jsperf](http://jsperf.com). – Pointy Sep 10 '11 at 22:35
  • 11
    [Benchmark](http://jsperf.com/literal-vs-new-23) – Raynos Sep 10 '11 at 22:40
  • Note the keyword new. This means "please be less efficient". It doesn't ever make sense, and requires the browser to do the normal instantiation instead of trying to do optimizations. – beatgammit Sep 10 '11 at 22:43
  • @tjameson my understanding from ES5 is that `[] === new Array()` – Raynos Sep 10 '11 at 22:46
  • @Raynos: Running the OP's code on my system produces similar results (`[]` being faster) but when running the benchmark you linked to, `[]` winds up actually being slower. O_o (Ran it multiple times to be sure. It always results in less ops/sec than any of the other snippets.) – cdhowie Sep 10 '11 at 22:47
  • This part of question is already discussed [here](http://stackoverflow.com/questions/4292048/why-use-instead-of-new-object-and-use-instead-of-new-array-and-true-fal/4292494#4292494) and [here](http://stackoverflow.com/questions/3386095/javascript-does-better-to-write-var-arr-then-var-arr-new-array) – Bakudan Sep 10 '11 at 22:47
  • @Raynos so does that mean [3] === new Array(3)? – kinakuta Sep 10 '11 at 22:49
  • 2
    @kinakuta no. They both create new non equal objects. I meant `[]` is equivelent to `new Array()` in terms of source code, not objects returned form expressions – Raynos Sep 10 '11 at 22:52
  • @kinakuta No! a = [3] will make an array with single element, new Array(3) will make an array with 3 elements. – Bakudan Sep 10 '11 at 22:54
  • Yes, I'm aware of what gets returned, I'm looking for clarification on how [] === new Array(); – kinakuta Sep 10 '11 at 22:55
  • This isn't very important. For almost all practical applications, the performance difference, which will vary from one browser to another, will be utterly insignificant. There will almost always be performance bottlenecks orders of magnitude more significant than the method used to create an array. – Tim Down Sep 10 '11 at 23:26
  • 1
    Yes, it's not very important. But I like to know. – Mohsen Sep 10 '11 at 23:31
  • Slightly off topic, but I found that there is also a HUGE memory usage difference. If I create an Array of 1000000 empty arrays inside, using array constructor it takes about 85MB, and when literal notation is used it takes about 40MB. (tested on chrome snapshots). – Oskar Skuteli Oct 26 '14 at 20:49
  • there is a persformance difference because the literal notation first transforms this to a temp object and then works upon it. – Saksham Feb 03 '16 at 14:22

5 Answers5

194

Further expanding on previous answers...

From a general compilers perspective and disregarding VM-specific optimizations:

First, we go through the lexical analysis phase where we tokenize the code.

By way of example, the following tokens may be produced:

[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)

Hopefully this should provide you a sufficient visualization so you can understand how much more (or less) processing is required.

  1. Based on the above tokens, we know as a fact ARRAY_INIT will always produce an array. We therefore simply create an array and populate it. As far as ambiguity, the lexical analysis stage has already distinguished ARRAY_INIT from an object property accessor (e.g. obj[foo]) or brackets inside strings/regex literals (e.g. "foo[]bar" or /[]/)

  2. This is miniscule, but we also have more tokens with new Array. Furthermore, it's not entirely clear yet that we simply want to create an array. We see the "new" token, but "new" what? We then see the IDENTIFIER token which signifies we want a new "Array," but JavaScript VM's generally do not distinguish an IDENTIFIER token and tokens for "native global objects." Therefore...

  3. We have to look up the scope chain each time we encounter an IDENTIFIER token. Javascript VMs contain an "Activation object" for each execution context which may contain the "arguments" object, locally defined variables, etc. If we cannot find it in the Activation object, we begin looking up the scope chain until we reach the global scope. If nothing is found, we throw a ReferenceError.

  4. Once we've located the variable declaration, we invoke the constructor. new Array is an implicit function call, and the rule of thumb is that function calls are slower during execution (hence why static C/C++ compilers allow "function inlining" - which JS JIT engines such as SpiderMonkey have to do on-the-fly)

  5. The Array constructor is overloaded. The Array constructor is implemented as native code so it provides some performance enhancements, but it still needs to check for arguments length and act accordingly. Moreover, in the event only one argument is supplied, we need to further check the type of the argument. new Array("foo") produces ["foo"] where as new Array(1) produces [undefined]

So to simplify it all: with array literals, the VM knows we want an array; with new Array, the VM needs to use extra CPU cycles to figure out what new Array actually does.

JSPP
  • 2,733
  • 1
  • 16
  • 11
  • isn't a = new Array(1000);for(from 0 to 999){a[i]=i} faster than a = [];for(from 0 to 999){a[i]=i} because of allocation overhead though? – martian17 Dec 10 '19 at 03:51
  • Just made a test case. new Array(n) is faster in cases where you know the size of the array ahead of time https://jsperf.com/square-braces-vs-new-array – martian17 Dec 10 '19 at 03:59
29

One possible reason is that new Array requires a name lookup on Array (you can have a variable with that name in scope), whereas [] does not.

hammar
  • 138,522
  • 17
  • 304
  • 385
  • 4
    Checking arguments may contribute too. – Leonid Sep 10 '11 at 22:49
  • `Array` excepts both one argument `len` and multiple arguments. Where as `[]` only accepts multiple arguments. Also firefox tests show almost no difference. – Raynos Sep 10 '11 at 22:49
  • I think there's some truth to that. Running OP's loop test in an IIFE makes a *(relatively)* substantial impact on the performance. Including `var Array = window.Array` improves the performance of the `new Array` test. – user113716 Sep 10 '11 at 23:12
  • I don't think that's right because this console.time('more vars new'); for(var i=0; i<200000; i++){ var arr = new Array() }; console.timeEnd('more vars new'); more vars new: 390ms and this console.time('more vars new'); var myOtherObject = {}, myOtherArray = []; for(var i=0; i<200000; i++){ var arr = new Array() }; console.timeEnd('more vars new'); more vars new: 369ms Returns same time – Mohsen Sep 11 '11 at 00:27
2

Also, interesting, if the length of the array is known in advance (elements will be added just after creation), the use of an array constructor with a specified length is much faster on recent Google Chrome 70+.

  • "new Array( %ARR_LENGTH% )" – 100% (faster)!

  • "[]" – 160-170% (slower)

Chart with results of the measures.

The test can be found here - https://jsperf.com/small-arr-init-with-known-length-brackets-vs-new-array/2

Note: this result tested on Google Chrome v.70+; in the Firefox v.70 and IE both variants almost equal.

Oleg Zarevennyi
  • 2,753
  • 1
  • 21
  • 21
2

Good question. The first example is called an array literal. It is the prefered way to create arrays among many developers. It could be that the performance difference is caused by checking the arguments of the new Array() call and then creating the object, while the literal creates an array directly.

The relatively small difference in performance supports this point I think. You could do the same test with the Object and object literal {} by the way.

1

This would make some sense

Objects literals enable us to write code that supports lots of features yet still make it a relatively straightforward for the implementers of our code. No need to invoke constructors directly or maintain the correct order of arguments passed to functions, etc.

http://www.dyn-web.com/tutorials/obj_lit.php

lnguyen55
  • 737
  • 6
  • 16