Kent Weigel Kent Weigel - 2 days ago 4
Javascript Question

If two JavaScript arrays of objects share elements, is all non-shared memory garbage-collected when one array is no longer referenced?

When two arrays have an element which points to (references) the same object, and you change the object via one array, it changes in the other array, as I have proven to myself in the first snippet below.

My question is, if array a1 is referenced in other code, such as an event handler, and a2 is not referenced anywhere else and goes out of scope, then do all "major" browsers garbage-collect the memory used by the a2 array itself, including pointers to the objects, and the memory for the object created in the 2nd push in the snippet below. If so, then since a2 no longer has pointers to the objects in a1, then if a1 finally goes out of scope, then will all of it's associated memory, including all objects it points to, be reclaimed by the GC, assuming no other pointers, besides those associated with a1 and a2, reference those objects?

I know it seems academic for this simple example, but I am writing an algorithm (see 2nd snippet) to make a nested object from a flattened version of the same data in an array, and in doing so I use a temp array which has elements pointing to each object in the original array. I plan to call it an indefinite amount of times, and I want to make sure I'm not leaking memory. There will be many more elements in the array than what is in the snippet.

I also know that there are other SO questions which have strong similarities to this one, and the answers have been helpful, but I don't think that anyone has definitively answered each part.



var a1 = [{first: 1, second: 2}, {first: 4, second: 2}, {first: 3, second: 4}];
var a2 = [a1[2]];

a2.push(a1[1]);
a2.push({first: 5, second: 8});

console.log('a1 = ' + JSON.stringify(a1, null));
console.log('a2 = ' + JSON.stringify(a2, null));

a2[0].first = 7;
a2[1].second = 9;

console.log('a1 = ' + JSON.stringify(a1, null));
console.log('a2 = ' + JSON.stringify(a2, null));







var events = [
{
"id": 7,
"parentId": 4,
"name": "Sub7",
"expected": 400,
"actual": 100
},
{
"id": 2,
"parentId": 1,
"name": "Sub2",
"expected": 200,
"actual": 100
},
{
"id": 4,
"parentId": 1,
"name": "Sub4",
"expected": null,
"actual": 100
},
{
"id": 8,
"parentId": 1,
"name": "Sub8",
"expected": 250,
"actual": 100
},
{
"id": 1,
"parentId": null,
"name": "Main",
"expected": null,
"actual": 100
},
{
"id": 6,
"parentId": 4,
"name": "Sub6",
"expected": 300,
"actual": 100
}
];

var temp = [];
var parent;

for (var i = 0; i < events.length; i++) {

if (temp[events[i].id]) {
Object.assign(temp[events[i].id], events[i]);
} else {
temp[events[i].id] = events[i];
temp[events[i].id].children = [];
}

var parentId = events[i].parentId;
if (!parentId) {
parent = temp[events[i].id];
} else {
if (!temp[parentId]) {
temp[parentId] = {
id: parentId,
parentId: undefined,
name: undefined,
expected: undefined,
actual: undefined,
children: [temp[events[i].id]]
}
} else {
temp[parentId].children.push(temp[events[i].id]);
}
}

delete temp[events[i].id].parentId;
}

temp = undefined;

document.write('<code><pre>' + JSON.stringify(parent, null, 2) + '</pre></code>');




Answer

It's actually very simple. As soon as items are no longer reachable via code (something goes out of scope), it is marked for deletion. Whether it is garbage collected at that moment is a detail of the implementation, but it will no longer be available in code.

So, when array2 goes out of scope, it's data will go away, but if an element in array2 is used in array1, that single piece of data will not go away.

Here's more on that.

Comments