2014-02-21 2 views
9

내가 어떻게 circular references cause memory leaks in IE에 대해 읽고 있었다, 그러나 나는 순환 참조 휴식을 폐쇄 내에서 클로저를 사용하는 예에 꽤 혼란스러워했다 :이중 폐쇄가 순환 참조를 끊는 방법은 무엇입니까?

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
    }; 
    (function() { 
     var el = document.getElementById('el'); 
     el.onclick = clickHandler; 
    })(); 
} 

내 머리가 모두 폐쇄가있는 무엇에 언급 된 것과 wrangled있어를 , 이는 스코프 객체이다. 누군가 MDN보다 명시 적으로 더 자세히 설명 할 수 있습니까? 감사. 당신이

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
     // can access `el` here 
    }; 
    var el = document.getElementById('el'); 
    el.onclick = clickHandler; 
} 

이 있다면

답변

8

elclickHandler에 대한 참조를 가지고 있지만, 그것은 폐쇄 때문에 clickHandler 또한, el에 대한 참조를 가지고있다. 새로운 범위를 도입하여

(IE)에서 -> 순환 참조하면 로컬el을하므로 그것은 clickHandler, ->없이 원형 ​​기준으로 액세스 할 수 없습니다.

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
     // cannot access `el` here 
    }; 
    (function() { 
     // `el` is local to this immediately invoked function 
     var el = document.getElementById('el'); 
     el.onclick = clickHandler; 
    })(); 
} 

그래서, 메모리 누출이 문제의 해결책은 하지이 다른 폐쇄를 도입하고, 그 하나의 방향으로 서로 "보호막"값 (하는 새로운 범위을 만들어야한다 가장 작은). 내가으로 이동 엄지 손가락의

+0

첫 번째 예에서 'el'이 'clickHandler'에서 명시 적으로 참조되지 않았더라도 'el'은 여전히 ​​clickHandler의 범위 객체에 존재 했습니까? 즉, 'clickHandler' *가'el '을 참조 할 수 있다고해도'clickHandler'는 명시 적 참조가 있거나없는 'el' 참조에 액세스 할 수 있습니까? 따라서'clickHandler'의 scope 객체에서'el'과'el' 객체에서'clickHandler' 사이에 순환 참조를 생성합니까? 단지 clickHandler의'this' 문이 그 참조를 만드는 scope 객체가 아닌'el'에 대한 순환 참조를 일으키지 않았 음을 확실히하고 싶습니다. –

+1

@TriNoensie : 아니요, '이'와 아무 관련이 없습니다. 함수가 생성되면 함수가 작성된 "범위"에 대한 참조도 가져옵니다. 즉, 함수가 작성된 범위에서 액세스 할 수있는 모든 변수에 대한 암시 적 * 참조를 갖습니다. 그리고 이로 인해 IE에서 문제가 발생했습니다. –

3

규칙 : 자바 스크립트 클로저

가 생성하는이 기능을 중첩 될 거기 가지고 있으며, 내부 기능에 액세스 할 수 있어야합니다 또는 그냥 "터치"를 가정 해 봅시다 (기준에 대해 참조한다 짧게) 외부 함수의 변수. 이 두 가지 기준 중 하나라도 발견되지 않으면 자바 스크립트에 클로저가 없습니다.

위의 단락에서 언급 한 변수가 외부 함수에서 DOM 요소 일 때 메모리 누수가 발생합니다.

분명히
function addHandler() { 
    var el = document.getElementById('el'); 
    el.onclick = function() { 
     this.style.backgroundColor = 'red'; 
    }; 
} 

, 거기에 다른 함수 안에 중첩 하나 개의 함수이며, 내부 기능 (엘) 변수의 속성에 할당됩니다 : 모질라 기사에서

, 이제 첫 번째 예제를 방문하자 바깥 쪽 범위에 클로저가 만들어집니다. 이 변수 el도 DOM 요소이므로이 기사에서 설명한대로 메모리 누수가 발생합니다. 당신이 게시 두 번째 예에서

,
function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
    }; 
    (function() { 
     var el = document.getElementById('el'); 
     el.onclick = clickHandler; 
    })(); 
} 

이 외부 기능, 그리고이 외부 함수 내에서이 중첩 된 (내부) 기능은 중첩,하지만 그들은 하나가 아닌 의미 같은 수준에

다른 내부에 중첩됩니다. 두 번째 중첩 된 함수는 외부 함수에서 로컬 변수 (clickHandler)에 액세스 할 수 있으므로 클로저가 만들어집니다. 그러나 외부 함수에서이 로컬 변수 (clickHandler)가 DOM 요소가 아니기 때문에 메모리 누수가 발생하지 않습니다. 로컬 변수 el은 두 번째 중첩 함수의 로컬이고 외부 함수 addHandler()에 정의되어 있지 않기 때문에 메모리 누수에 기여하지 않습니다.즉, 두 번째 중첩 함수의 로컬이므로 첫 번째 중첩 함수에서 액세스 할 수 없으므로 메모리 누수가 발생하지 않습니다.

관련 문제