2016-11-30 3 views
0

Если у двух массивов есть элемент, который указывает на (ссылки) один и тот же объект, и вы меняете объект через один массив, он изменяется в другом массиве, как я доказал себе в первом фрагменте ниже.Если два массива JavaScript объектов разделяют элементы, является ли сборщик мусора, не связанный с общей памятью, когда один массив больше не ссылается?

Мой вопрос в том, что если массив a1 указан в другом коде, например обработчик события, а a2 не упоминается нигде и не выходит за пределы области видимости, тогда все «крупные» браузеры мусора собирают память, используемую сам массив a2, включая указатели на объекты, и память для объекта, созданного во втором нажатии в фрагменте ниже. Если это так, то, поскольку a2 больше не имеет указателей на объекты в a1, то, если a1, наконец, выходит из области видимости, тогда вся связанная с ним память, включая все объекты, на которую она указывает, будет исправлена ​​GC, не предполагая никаких других указателей , кроме тех, которые связаны с a1 и a2, ссылаются на эти объекты?

Я знаю, что это академический пример для этого простого примера, но я пишу алгоритм (см. Второй фрагмент), чтобы сделать вложенный объект из сплющенной версии тех же данных в массиве, и при этом я использую временную массив, который содержит элементы, указывающие на каждый объект в исходном массиве. Я планирую назвать это неопределенным количеством раз, и я хочу убедиться, что я не утечка памяти. В массиве будет больше элементов, чем в фрагменте.

Я также знаю, что есть другие вопросы, которые имеют сильное сходство с этим, и ответы были полезны, но я не думаю, что кто-то окончательно ответил на каждую часть.

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>');

ответ

1

Это на самом деле очень просто. Как только элементы больше не доступны через код (что-то выходит за рамки), оно помечено для удаления. Будь то сборка мусора, собранная в этот момент, является деталью реализации, но она больше не будет доступна в коде.

Итак, когда массив2 выходит за пределы области видимости, данные будут удалены, но если в массиве 1 используется элемент array2, этот единственный фрагмент данных не исчезнет.

Here's more on that.

+0

Эта страница Mozilla, с которой вы связались, и фразы на нем, такие как «mark and sweep», которые привели меня к другим источникам информации, оставили меня достаточно уверенным в том, что мне не нужно беспокоиться об использовании временного массива в моем примере, хотя он будет использоваться много раз для многих элементов. –

+0

Правильно. Лучшим советом является сохранение ваших объявлений в минимальном объеме, который вы можете, так что, когда функции заканчиваются, собираются локальные переменные. –

1

Короткая версия такова: если код не может получить доступ к нему, он будет мусора.

Вы можете представить график, начинающийся с корневого узла (думаю, window), и каждый последующий узел представляет собой данные, к которым можно получить доступ с этого узла. В вашем случае, вы получите что-то вроде этого:

root --> event handler --> array1 --- 
            V 
            object 
            ^
          array2 --- 

Вы можете видеть, что есть путь назад к корню с помощью array1. Такой путь не существует для array2. Поэтому array2 будет очищен, и любые значения, которые также не имеют ссылки на корень, также будут очищены.

object имеет путь назад к корню через array1. Поэтому array2 с ссылка будет собрана, но фактические данные , который составляет object, не будет.

+0

Я всегда думал только об этом с точки зрения подсчета ссылок, где был огромный массив где-то с объектными указателями и количество оставшихся ссылок на него. Ваше объяснение того, как сборщик мусора проходит через все ссылки из некоторого корневого узла, чтобы определить, существуют ли ссылки, по-прежнему представляется более надежным, но, возможно, менее быстрым. Мне нужно будет изучить это дальше. У вас случайно есть ссылка, где они говорят о вашем методе графика, или я должен перейти непосредственно к спецификации W3? –

+0

@KentWeigel [подсчет ссылок] (https://en.wikipedia.org/wiki/Garbage_collection_ (computer_science) #Reference_counting) - это один из методов, который использовался, но [приводит к неприятным утечкам.] (Http: //javascript.crockford .com/memory/leak.html). Как работает сборщик мусора, разработчики двигателей, а не орган стандартов. –

+0

@KentWeigel Chrome (и другие двигатели, я бы предположил) используют [коллективный метод генерации] (https://en.wikipedia.org/wiki/Garbage_collection_ (computer_science) #Generational), который работает как выше, но улучшает производительность только сравнивая объекты с более старыми «поколениями». Вы можете найти дополнительную информацию об этом [здесь.] (Http://v8project.blogspot.com/2015/08/getting-garbage-collection-for-free.html) Пока узел имеет ссылку на старшее поколение , он по-прежнему доступен. Сравнивая по поколениям, он не требует полной древовидной ходьбы для обеспечения доступности ссылки. –

 Смежные вопросы

  • Нет связанных вопросов^_^