2011-04-18 3 views
2

최근 인터뷰를하는 동안 "이 코드처럼 DOM 요소를 참조 할 때 클로저를 사용하면 위험 할 수 있습니다."라는 질문을 받았습니다.클로저에서 DOM 요소를 참조하는 중 IE 메모리 누수가 있습니까?

var firstNameValue = (function(elementId) { 
    var firstName = document.getElementById(elementId); 
    return firstName.value; 
})("firstName"); 

분명히 위의 코드는 IE에서 메모리 누수를 만듭니다. 주어진 이론적 근거는 꽤 모호했고 이해할 수 없었지만 분명히 이것은 구형 IE 버전에만 적용될 수 있습니까?

누구든지 이것에 대해 자세히 설명 할 수 있습니까?

+1

질문자는 매우 벙어리 또는 매우 영리 중 하나입니다. Dumb은 closure 나 메모리 누수가 없기 때문에 전체가 다음과 같습니다 :'var firstNameValue = document.getElementById ('firtName'). value;'. 클로저와 메모리 누수에 대한 언급은 실제 문제에서 산만 해지기 때문에 매우 똑똑합니다. 코드의 불필요한 복잡성 때문입니다. – RobG

+0

"메모리 누수 문제"는 IE8에서 수정 된 것으로보고되었습니다. 그러나 @RobG가 답변 한 것처럼이 방법으로 이전 브라우저에서 메모리 누수가 발생했을 수도 있습니다. 다음 MSDN 페이지는 IE7 및 이전 버전에서 메모리 누수가 발생할 수있는 일련의 테스트 사례를 나열합니다.이 패턴은 포함되어 있지 않습니다. http://msdn.microsoft.com/en-us/library/dd361842(VS.85).aspx – MrWhite

답변

5

DOM에 의해 할당 된 메모리를 처리하기 위해 IE의 내장에 사용되는 가비지 수집기는 JScript 엔진에서 할당 한 메모리를 해제하는 방법을 모르고 있습니다. 따라서, 그것은 단지 그런 것들을 무시합니다.

DOM 요소 (또는 그와 비슷한 것)에 이벤트 처리기를 바인딩하고 이벤트 처리기는 다른 함수 호출 내에서 만들어진 함수이고 다른 함수는 10 억 개가 포함 된 로컬 배열을가집니다. DOM 엘리먼트 자체가 쓰레기로 처리 된 이후에도 수십억 가지의 것들이 계속 오랫동안 생겨났다. 그리고 심지어 그것이 포함되어있는 페이지이 오랫동안 사라진 후에도 (나는 생각한다;

function bindHandler(domElement) { 
    var hoHumWhatever = generateGiganticObjectNow(); 

    domElement.onclick = function() { 
    alert("oww you clicked me"); 
    }; 
} 

이제 "hoHumWhatever"변수가 클로저에 유지됩니다. 페이지가 다시로드되거나 요소가 버려지도록 DOM을 수정하면 DOM 가비지 수집기가 JScript 소유 메모리를 가리키는 특성을 사용하여 작업을 수행하지 못합니다. 반면 JScript는 DOM 노드가 해제되었음을 알지 못하므로 closure 메모리가 여전히 참조된다고 생각합니다.

일부 내용은 정확하지 않을 수 있음을 인정하지만 이는 기본 문제입니다. 다양한 사람들이 Crockford 씨와 quirksmode에서 (필자는) ppk를 포함하여 이것에 대해 썼다. 더 신중하게 당신이 게시 코드를 다시 읽기시

편집, 나는 유사하지만 반대의 경우의 예가 될 수 있다고 생각 : 작은 함수는 DOM 값의 일부에 대한 참조를 반환하므로 어쩌면 JScript가 DOM 메모리에 매달려 있다고 말하는 것일 수도 있습니다 (반대의 경우도 마찬가지입니다). 자,이 특별한 경우에 나는 조금 의심 스럽습니다. 왜냐하면 저는 DOM 속성에 대한 간단한 참조를 제외하고 그 closure에서 "탈출"하는 것을 보지 못했기 때문에 원시적 인 문자열 인스턴스 여야하고 그래서 정말로 ' 문제를 일으킬 수 있습니다. 이 문제는 기만적 일 수 있습니다. 그러나 나는 단지 여기 앉아서 머리를 찰 겁니다.

+0

"스택 오버플로"에 대해 말하기 :) –

+0

나는 당신과 동의한다. 누수가 발생합니다. ** 폐쇄가 없다 **, "작은 함수"(일부분은 iife라고 함)는 지속되지 않으며, 그 경우에도 외부 범위의 변수를 참조하지 않습니다 (DOM에 대한 참조를 얻지 만 요소). 유일한 누수는 DOM 참조에서 발생하며 누수가 발생하면 어떻게 그 지구를 피합니까? IE 메모리 누출의 주된 문제는 DOM 요소가 포함 된 순환 참조 (예 : 귀하의 예) 였지만 해결 된 문제입니다 (알고있는 한). – RobG

4

다음 코드는 클로저 (아래 참조) 또는 메모리 누수를 생성하지 않습니다.

var firstNameValue = (function(elementId) { 
    var firstName = document.getElementById(elementId); 
    return firstName.value; 
})("firstName"); 

IE 6 조사의 비트 코드가 메모리 누설을 생성하지 않는 것을 나타낸다. 난 큰 슬래브와 Lorem ipsum 및 고유 ID를 실행 한 다음 위 코드마다 1000 개의 익명 함수를 실행하고 페이지를 새로 고칠 때마다 페이지를 열 때까지 메모리 사용으로 고집스럽게 반환되었습니다. 페이지에 수천 가지 요소를 더 추가하여 100MB를 넘지는 않았지만 IE는 계속 원래 크기로 돌아 왔습니다.

이 질문은 마땅한 질문입니다 (즉, "영구적 인 폐쇄가없고 순환 참조가 없으므로 메모리 누수가 없습니다").

트릭 질문이 아닌 경우 누구에게 글을 쓴지 또는 질문을 통해 실제 데모를 제공 할 수 있는지 확인하십시오.

클로저의 간단한 설명은 ECMAScript를 이너 기능이 가능하다

폐쇄; 함수 정의와 함수 표현은 안에 있으며 다른 함수의 함수 표가됩니다. 그리고 그 내부 함수는 로컬 변수 변수 모두에 대한 액세스를 허용하고 외부의 함수 내에 내부 함수를 선언했습니다. 내부 기능 중 하나 인 이 포함 된 함수에서 외부로 액세스 할 수있게되면 클로저가 형성되어 외부 함수 이 반환 된 후에 이 실행될 수 있습니다. 어느 시점에서 여전히 은 로컬 변수, 매개 변수 및 내부 함수 외부 함수의 선언에 액세스 할 수 있습니다. 해당 로컬 변수, 매개 변수 및 함수 선언 (처음에는)은 외부 함수가 반환 될 때의 값을 으로 가지고 있으며 은 내부 함수와 상호 작용할 수 있습니다.

리처드 Cornford 등, "자바 스크립트 클로저"http://www.jibbering.com/faq/notes/closures/

관련 문제