2009-08-21 2 views
4

어떤 이유로 든 pageNumber는 loopCounter에 대한 루프의 마지막 값이됩니다. 이제는 closure 자체에서 loopCounter를 직접 사용하고 있지만 그렇지 않다는 것을 이해할 수 있습니다. 아래 코드에서 알 수 있듯이 closure에서 loopCounter의 현재 값을 가져 오는 새 변수를 만듭니다.수정 된 클로저 문제에 대한 접근 가능성 ... 이길 방법?

(JavaScript가 모든 것을 참조 유형으로 취급한다고 가정하면) pageNumber는 loopCounter에 대한 참조를 취하고 있으므로 새 pageNumber를 여러 번 만들지도 않고 항상 loopCounter 객체를 가리키고 있습니다. 따라서 loopCounter가 끝나는 값은 pageNumber가 가리키는 값이됩니다.

어떻게 loopCounter를 가리 키지 않고 현재 loopCounter 값을 보유하는 반복마다 새 pageNumber를 만드나요?

for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++) 
{ 
    ... 
    var newDiv = document.createElement('div'); 
    ... 
    //trying to remove the reference to loopCounter 
    var pageNumber = loopCounter; 
    newDiv.onclick = 
    function(event) 
    { //Right here ---V 
     getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber); 
    }; 

    ... 
} 

솔루션 아래에 몇 가지 답변에

감사 :

function createClickMethod(loopCounter, link) 
{ 
    var pageNumber = loopCounter; 

    return function(event) { getResultUsingUrl(link + "&pageNumber=" + pageNumber); }; 
} 

내가 같이 호출 할 수 있습니다

newDiv.onclick = createClickMethod(loopCounter, result.PagerPreLink); 

또는 내가 jQuery를 사용하려면 .. 아래 제안 :

jQuery(newDiv).click 
(
    createClickMethod(loopCounter, result.PagerPreLink) 
); 
+0

result.StartingPoint 무엇을 쓸 수 있을까? –

+0

비동기 메서드 호출에서 반환 된 개체를 반환합니다. –

답변

9

다른 그것이 범위 지정 문제입니다 말했다. JS 라이브러리를 사용하지 않고 다음과 같이 할 수 있습니다.

newDiv.onclick = (function() { 
    var num = loopCounter; 
    return function(evt) { 
     console.log(num); 
    } 
})(); 

값 주변에 다른 클로저를 만들어야합니다.

+0

그래서 기본적으로 범위를 명확하게 유지하기 위해 이벤트 메서드를 만드는 메서드가 필요합니다. –

+0

예. JS 범위는 함수로 제한되므로 블록이 아닌 새 함수를 만들어야합니다. 이것은 본질적으로 다양한 JS 라이브러리가 이벤트 연결 메소드로 수행해야하는 작업입니다. – seth

0

onclick 폐쇄는 범위를 유지하지 않으므로 결과에 액세스 할 수 없습니다.

쉽고 강력한 솔루션으로 dojo.hitch을보고 범위를 제어 할 수 있습니다.

+0

그 시점에서 dojo.forEach와 dojo.connect를 사용할 수 있습니다. – seth

1

결과입니다 .StartingPoint는 실제로 기본 유형입니다 (예 : 실제 숫자 유형? 그렇지 않다면, 아마도 여러분은 그 객체에 대한 참조를 얻고 있고 문자열 연결이 여러분을 위해 타입 - 강제를 수행하고 있다는 것입니다. 대신 다음을 시도하십시오.

var pageNumber = new Number(loopCounter); // force coercion 
+0

이 메소드는 pageNumber 참조를 참조하고 해당 메소드가 여전히 loopCounter를 가리 킵니까? –

5

매번 새로운 pageNumber를 만들지는 않습니다. 당신은 오직 하나만 가지고 있습니다. JavaScript의 범위는 함수 범위를 넘어 확장되지 않습니다. 함수에서 선언 한 "var"는 루프의 내부 또는 외부에서 함수의 맨 위에서 올바르게 선언 한 것과 동일하게 작동합니다. 모든 사람처럼

http://javascript.crockford.com/code.html

+0

흥미롭고 오래된 동적 범위 지정. – Zoidberg

2

자바 스크립트 클로저는 변수에 대한 참조를 저장하므로 모든 onclick 핸들러가 동일한 변수를 사용합니다.

는이 같은 중간 함수에서 변수를 캡처해야합니다

그런 다음
function buildClickHandler(pageNumber) { 
    return function(event) { //Create and return a new function 
     getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber); 
    } 
} 

, 다음과 같이 onclick 핸들러를 생성하는 기능을 사용 :

for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++) { 
    //... 

    var newDiv = document.createElement('div'); 

    newDiv.onclick = buildClickHandler(loopCounter); 
} 

buildClickHandler를 호출 할 때마다이 (가) 작성 자체 변수가있는 별도의 클로저입니다. 여담으로


, DOM 조작을 할 jQuery 사용을 고려; 원시 DOM API보다 훨씬 쉽습니다. 당신의 예에서

, 당신은

$('<div />').click(buildClickHandler(loopCounter)); 
+0

소원 나는 올바른 것으로 두 표시 할 수 있습니다. 당신이 제안한 것처럼 jquery를 사용할 가능성이 높습니다. 그러나 이것이 일반적인 것이기를 바랍니다. 그러면 더 많은 사람들이 대답 할 것입니다. –

관련 문제