7

So, I was thinking how arrays are stored in memory in JavaScript.

I already read How are JavaScript arrays represented in physical memory? , but I couldn't find my answer.

What I'm thinking is more about the memory location of the array units. In C for example, you need to define the size of the array when you define them. With this, C defines a whole block of memory, and it can look the exact location of each unit.

For example:

int array[10]; // C knows the memory location of the 1st item of the array

array[3] = 1   // C can do that, because it can calculate the location 
               // of array[3] by doing &array + 3 * (int size)

In JS, you can grow the size of an array after allocating memory to other stuff, which means JS doesn't work with the "block" type of array.

But if arrays are not a single block of memory, how does JS calculate where each unit is? Do JS arrays follows a linked list type of structure?

João Haas
  • 1,883
  • 13
  • 13
  • https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array might help? – evolutionxbox Apr 23 '18 at 22:25
  • 3
    I don't understand how the answer in the duplicate doesn't answer this. – Kevin B Apr 23 '18 at 22:26
  • 2
    It's implementation dependent. The language specification does not enforce how an engine must store arrays, only how they behave. – Paul Apr 23 '18 at 22:26
  • 1
    @evolutionxbox That is an API reference, not a reference on how Arrays are implemented internally. – Scott Marcus Apr 23 '18 at 22:27
  • @ScottMarcus damn. I didn’t check in detail. I had hoped it would be useful. – evolutionxbox Apr 23 '18 at 22:27
  • 1
    Probably not, but AFAIK the standard only defines the interface arrays should have, the exact model is left to the implementation. `ArrayBuffer`s on the other hand are meant to be contiguous chunks of memory, precisely for performance reasons. – Máté Safranka Apr 23 '18 at 22:28
  • The answer of the duplicate question mentions that it's a hash table implementation, with the array indexes being the keys. – Jacob Apr 23 '18 at 22:37

2 Answers2

5

One thing I would recommend everyone is that node.js recently became a first-class citizen of Chrome V8, so I would recommend studying V8 to see not only how it handles these implementation details but also why.

First, This article should prove beneficial to readers because of its focus on writing optimized isomorphic JavaScript:

https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e

The above article goes into details about how the JIT (Just In Time) compiler works, so you should be able to derive the exact questions you have after reading it.

Here is an exerpt:

Arrays: avoid sparse arrays where keys are not incremental numbers. Sparse arrays which don’t have every element inside them are a hash table. Elements in such arrays are more expensive to access. Also, try to avoid pre-allocating large arrays. It’s better to grow as you go. Finally, don’t delete elements in arrays. It makes the keys sparse.

Second, I would also recommend reading this and then working outward with respect to V8: http://www.jayconrod.com/posts/52/a-tour-of-v8-object-representation

Third, as a matter of critical bonus facts, I read this answer a while ago and I mentally revisit it from time to time. I am extremely surprised I just found it now. I literally Googled "stack overflow optimize train tracks" and found it. Thanks Google: Why is it faster to process a sorted array than an unsorted array?

Yes, that answer does have 27,000 positive votes.

That article talks about branch prediction, and I would like you to be aware of that because it could have some implications on how you work with data in general not just arrays. Again, note the first article I linked, and pay attention while it is describing the order of keys on an Object.

Performance can be optimized by understanding the implementation details and understanding why the problems were solved that way.

Finally, everything is an Object in JavaScript unless it is a scalar value, which we call primitives--String, Number, Boolean, etc.

Here is an example for thought provoking purposes:

const arr = ['one', 'two', 'three']

const sameArr = {
  0: 'one',
  1: 'two',
  2: 'three',
}

We could then destructure our Array as if it were an Object:

const yolo = ['one', 'two', 'three']

const {
  0: one,
  1: two,
  2: three,
} = yolo

console.log('Pretty cool:', one, two, three)

You can get some hints from that example as to why changing the order of keys could wreak havoc on the underlying hash table. Just because you can't see the keys doesn't mean they aren't there and affected.

In the above example, if it were a map, you could do sameArr.get('0') and JavaScript would reasonably know exactly where that is in the numerical table.

I would also recommend being careful reading old JavaScript material because of the overhauls of ES6. I feel the most comfortable directing you to V8 material.

agm1984
  • 15,500
  • 6
  • 89
  • 113
4

Unlike C or other compiled languages that are proprietary, JavaScript is an ECMAScript implementation. The details of the implementation are not standardized and are specific to each vendor's implementation. In short, the low level details of how the language is implemented is a black box and while you can certainly dive into the internals of a particular vendor's implementation, there is no standard on this and implementations will vary from one vendor to another.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • 6
    I'm downvoting because, while this is technically correct, the reasoning is completely absurd. The way arrays behave has nothing to do with whether or not the language is proprietary. Arrays in JavaScript work this way because that is how the language is designed. This has nothing to do with _how_ or even _if_ that design is specified. Even worse, this has nothing to do with whether a language is compiled or not, and that in its turn has nothing to do with whether or not it is proprietary – Aluan Haddad Apr 23 '18 at 22:48
  • 1
    @AluanHaddad It's not absurd. I brought up proprietary languages because the compilers for those languages are not subject to be implemented however a 3rd party decides to implement it. JavaScript, on the other hand, is completely dependent on every implementation simply producing the correct results, how the implementation gets to those results is not dictated by anyone. – Scott Marcus Apr 23 '18 at 22:53
  • 1
    That's not my point. A language could have the same relationship between specification and implementation while mandating C like array behavior. It doesn't have anything to do with compilation vs interpretation either. – Aluan Haddad Apr 23 '18 at 22:56
  • 1
    C is an ISO standard language, not proprietary. Also there is no standard implementation of C (much less a SINGLE implementation). Two of the best implementations are Microsoft Visual C and GNU C Compiler but there are others like Keil, Microchip, clang, SDCC etc. So C and javascript is very much comparable - both have no standard single implementation and both are implemented independently by competitors. Still, how arrays are implemented vary wildly – slebetman Apr 24 '18 at 00:40
  • 1
    Indeed, unlike ECMAScript, the various standards of C have very specific language that explicitly allow vendors to be creative and implement things that are different from other implementations: undefined behavior and implementation defined behavior – slebetman Apr 24 '18 at 00:42