Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are JavaScript arrays represented in physical memory?

It is my understanding that I can store mixed data in a JavaScript array, as well as change any element in the array to some other type. How does the interpreter keep track of what place in physical memory any element is at. Also how is the overwriting of the data in the next element prevented if I change an element to a larger data type.

I assume that arrays only store references to actual objects, and primitives are wrapped behind the scenes when placed in arrays.

Assuming this is the case, If I have a different handle on the primitive variable and change the value stored in the array is synchronicity maintained?

I know I probably already answered my own question, but I don't know for sure and I can't find any information on the matter.

like image 931
user3056052 Avatar asked Dec 02 '13 04:12

user3056052


People also ask

How is an array represented in JavaScript?

The array literal form uses the square brackets [] to wrap a comma-separated list of elements.

How an array is represented in memory?

Arrays are often represented with diagrams that represent their memory use. The diagram below is one typical way to represent the memory used by an array. Each box represents the amount of memory needed to hold one array element. For ints this is usually 4 bytes.

How are JavaScript objects stored in memory?

The heap is a different space for storing data where JavaScript stores objects and functions. Unlike the stack, the engine doesn't allocate a fixed amount of memory for these objects. Instead, more space will be allocated as needed. Allocating memory this way is also called dynamic memory allocation.

Are arrays contiguous in physical memory?

@daniel Yes it does. "everything that's contiguous within a page will be contiguous for both virtual memory and physical memory".


2 Answers

Normally, arrays allocate a contiguous block of memory of fixed length. However, in Javascript, arrays are Object types with special constructors and accessor methods.

Which means, a statement like:

var arr = new Array(100000); 

does not allocate any memory! In fact, it simply sets the value of the length property in the array. When you construct an array, you don't need to declare a size as they grow automatically. So, you should use this instead:

var arr = []; 

Arrays in Javascript are sparse which means not all the elements in the array may contain data. In other words, only the elements that actually contain data exist in the array. This reduces the amount of memory used by the array. The values are located by a key and not by an offset. They're simply a method of convenience and not intended to be used for complex numerical analysis.

Arrays in Javascript are not typed so the value of an element can be an object, string, number, boolean, function or an array. The main difference between an array and an object is the length property which has a value greater than the largest integer key in the array.

For example:

You could have an create an empty array and add two elements at index 0 and index 99. The length would be 100, but the number of elements in the array would be 2.

var arr = []; arr[0] = 0; arr[99] = {name: "John"}; console.log(arr.length); // prints 100 arr; // prints something like [0, undefined × 98, Object { name: "John"}] 

To answer your questions directly:

Q. It is my understanding that I can store mixed data in a JavaScript array, as well as change any element in the array to some other type. How does the interpreter keep track of what place in physical memory any element is at? Also, how is the overwriting of the data in the next element prevented if I change an element to a larger data type?

A. You probably know this by now if you've read my comments above. In Javascript, an array is a Hashtable Object type so the interpreter doesn't need to keep track of physical memory and changing the value of an element doesn't affect other elements as they're not stored in a contiguous block of memory.

--

Q. I assume that arrays only store references to actual objects, and primitives are wrapped behind the scenes when placed in arrays. Assuming this is the case, if I have a different handle on the primitive variable and change the value stored in the array is synchronicity maintained?

A. No, primitives are not wrapped. Changing a primitive that was assigned to an array will not change the value in the array as they're stored by value. Objects on the other hand are stored by reference, so changing the objects value will reflect that change in that array.

Here's an example you can try:

var arr = []; var obj = { name: "John" }; var isBool = true;  arr.push(obj); arr[1] = isBool;  console.log(arr[0]); // print obj.name console.log(arr[1]); // print true  obj.age = 40;        // add age to obj isBool = false;      // change value for isBool  console.log(arr[0]); // value here will contain age console.log(arr[1]); // value here will still be true 

Also, note that when you initialize an array in the following two ways, it has a different behavior:

var arr = new Array(100); console.log(arr.length);        // prints 100 console.log(arr);               // prints []  var arr2 = new Array(100, 200); console.log(arr2.length);       // prints 2 console.log(arr2);              // prints [100, 200] 

If you want to use Javascript Arrays as contiguous blocks of memory, you should look into using TypedArray. TypedArray's allow you to allocate a block of memory as a byte array and access the raw binary data more efficiently.

You can learn more about the intricacies of Javascript by reading the ECMA-262 spec (ver 5.1).

like image 94
Nick Avatar answered Oct 05 '22 21:10

Nick


Here is some food for thought. I made a jsperf to test a simple array optimization that some JavaScript engines implement.

The test case creates two arrays with a million elements each. The a array contains only numbers; the b array contains the same numbers except for the first element which is an object:

var a = [ 0 ], b = [ { valueOf: function() { return 0; } } ]; for( var i = 1;  i < 1000000;  ++i ) {     a[i] = b[i] = i; } 

The valueOf property of the object in the first element of the b array returns 0 so the arithmetic will be the same as the first array.

Then the two tests simply sum all the values for the two arrays.

Fast array:

var x = 0; for( var i = 0;  i < 1000000;  ++i ) {     x += a[i]; } 

Slow array:

var x = 0; for( var i = 0;  i < 1000000;  ++i ) {     x += b[i]; } 

As you can see from the test results in the jsperf, in Chrome the numeric array is about 5x faster, in Firefox the numeric array is about 10x faster, and in IE it's about 2x faster.

This doesn't directly reveal the internal structures used for the array, but it gives a pretty good indication that the two are quite different from each other.

like image 38
Michael Geary Avatar answered Oct 05 '22 20:10

Michael Geary