30

Javascript 엔진이 순환 참조를 처리하는 방법을 자세히 설명 할 수 있습니까? 브라우저 나 node.js간에 큰 차이점이 있습니까?Javascript/Garbage collector의 순환 참조

내가 말하고자하는 것은 객체 내의 명시적인 백/다음 참조입니다. 예 :

var objA = { 
    prop: "foo", 
    next: null 
}; 

var objB = { 
    prop: "foo", 
    prev: null 
}; 

objA.next = objB; 
objB.prev = objA; 

우리가 간다. console.log(objA)을 수행하면 무한 사슬을 만들었습니다. 큰 문제는이게 나쁜 것입니까? 명시 적으로 청소하지 않으면 메모리 누수가 발생합니까?

그래서 우리는

objA.next = null; 
objB.prev = null; 

해야합니까 또는 가비지 수집이 같은 별자리에 우리를 돌볼 것인가?

답변

53

모든 가비지 수집기가주기를 처리합니다.

주기는 순조로운 참조 계산을하는 경우에만 문제가됩니다.

대부분의 가비지 수집기는 순환 횟수를 처리 할 수없고 비효율적이기 때문에 다시 계산하지 않습니다. 대신, 그들은 "루트"(일반적으로 전역 변수와 스택 기반 변수)에서 시작하여 찾을 수있는 모든 참조를 따르고 "도달 가능한"것으로 모든 것을 표시합니다.

그런 다음 다른 모든 메모리를 다시 요구합니다.

사이클은 동일한 노드에 여러 번 도달한다는 의미이므로 아무런 문제가 없습니다. 처음으로 노드가 이미 "도달 가능"으로 표시되므로 GC는 이미 도달했음을 알게되고 노드를 건너 뜁니다.

참조 카운팅에 기반한 훨씬 더 원시적인 GC는 일반적으로 사이클을 감지하고 중단하는 알고리즘을 구현합니다.

간단히 말해서 걱정할 필요가 없습니다. IE6의 Javascript GC는 실제로 사이클을 처리하지 못했습니다 (잘못된 것일 수도 있습니다. 읽은 이후로 꽤 오랜 시간이 걸렸습니다. IE6을 만진 이후로 훨씬 더 오래되었습니다). 그러나 모든 현대 구현에서는 문제 없어.

가비지 컬렉터의 전체 지점은 메모리 관리를 추상화하는 것입니다. 이 작업을 직접해야하는 경우 GC가 손상되었습니다.

현대 가비지 수집 및 사용 된 표시 및 스윕 알고리즘에 대한 자세한 내용은 MDN을 참조하십시오.

+1

http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Closures#Closures가 잘못 되었습니까? – Sandro

+2

@Sandro가 내 대답을 다시 읽었습니다. :) 제정신의 GC는 사이클을 잘 처리합니다. IE6보다 새로운 모든 것은 정상적인 것으로 간주 될 수 있습니다. IE6를 지원해야한다면 부서진 사이클 처리에 대해 걱정해야합니다. 분명히 Google 가이드는 이러한 깨진 브라우저가 지원되어야한다는 가정하에 작성되었으므로 일부 추가 농구를 뛰어 넘어야합니다. – jalf

+0

@Sandro 그 예에서 특별한 점이 있습니다. DOM 요소는 순환 참조의 한 부분입니다. 일반적으로 페이지를 닫을 때까지 메모리가 누출됩니다. 그러나 올바르게 호출 한 경우 IE가 탐색 할 때 IE가 DOM에 대한 참조를 항상 제거하지는 않습니다. (분명히 일부 페이지가 어땠어?) –