2012-04-17 6 views
1

onClick 메서드를 사용하여 함수를 호출한다고 가정 해 봅시다. 이 같은자바 스크립트에서 재귀 함수, setTimeout 및 'this'키워드

<li class="inline" onclick="mve(this);" >TEMP</li> 

AND I이 닮은 JS 기능을 가지고

function mve(caller){ 
caller.style.position = "relative"; 
caller.style.left = (caller.style.left+20) +'px'; 
var foo = setTimeout('mve(caller)', 2000); 
} 

내 문제 소자 초기 ​​온 클릭 호출 후에 정의되지 않는다 (호출자가 참조)이다. 적어도 이것은 방화범이 끌고있는 말입니다.

나는 그것이 쉬운 해결책 일 것이라고 확신한다. 그렇다면 이유와 방법에 대한 간단한 설명은 어떨까요?

또한 그래서처럼 실행하는 경우 :

function mve(caller){ 
caller.style.position = "relative"; 
caller.style.left = (caller.style.left+20) +'px'; 
} 

내가 요소가 모든 클릭에 20 픽셀 오른쪽으로 이동 것이라고 생각하지만 그런 경우가 아니다. 생각?

답변

4

setTimeout()은 전역 범위에서 문자열 매개 변수를 실행하므로 사용자의 값인 this이 더 이상 존재하지 않으며 인수가 caller입니다. 이것은 setTimeout에 문자열 매개 변수를 사용하지 않는 많은 이유 중 하나입니다. 이 같은 실제 자바 스크립트 함수 참조를 사용하고 아주 쉽게 인수가 따라 통과지고 해결하는 문제이다 : 당신의 질문의 두 번째 부분에 대한

function mve(caller){ 
    caller.style.position = "relative"; 
    caller.style.left = (caller.style.left+20) +'px'; 
    setTimeout(function() { 
     mve(caller) 
    }, 2000); 
} 

, caller.style.left20px처럼에 단위를해야 할 것입니다 그래서 때를 20을 추가하면 20px20이되며 브라우저에서 알 수있는 값이 아니므로 아무 일도 일어나지 않습니다. 이처럼 뒷면에있는 단위를, 그것의 실제 수를 분석 할 수로 (20)를 추가하고 추가해야합니다 : 그것은 반복을 중지 할 수있는 방법이 기능에서 누락

function mve(caller){ 
    caller.style.position = "relative"; 
    caller.style.left = (parseInt(caller.style.left), 10) +20) + 'px'; 
    setTimeout(function() { 
     mve(caller) 
    }, 2000); 
} 

뭔가. 네가 지금 그것을 가지고 있기 때문에, 그것은 영원히 계속된다. 이 같은 반복의 숫자 중 하나를 전달 제안 할 수 있습니다

function mve(caller, iterationsRemaining){ 
    caller.style.position = "relative"; 
    caller.style.left = (parseInt(caller.style.left), 10) +20) + 'px'; 
    if (--iterationsRemaining) > 0) { 
     setTimeout(function() { 
      mve(caller, iterationsRemaining) 
     }, 2000); 
    } 
} 

또한, 당신이 정말 재귀 함수 아니라는 것을 알고 궁금 수 있습니다. mve() 함수가 setTimeout()을 호출하고 바로 종료되기 때문입니다. 얼마 후에 mve()의 다음 반복을 실행하는 setTimeout()이며 여러 함수 호출의 스택 프레임에 누적이 없으므로 실제 재귀가 없습니다. 코드를 한 눈에 재귀처럼 보이지만 기술적으로는 아닙니다.

+0

감사합니다. 이 질문에 대한 답뿐만 아니라 추가 통찰력과 분명한 발표로 자료를 쉽게 소화 할 수있었습니다. 대단히 감사드립니다. – T110

0

발신자가 첫 번째 통화 후에 범위를 벗어날 가능성이 있습니다.

var globalCaller; 
function onClickEvent(caller) { 
    globalCaller = caller; 
    mve(); 
} 

function mve() { 
    globalCaller.style.position = "relative"; 
    globalCaller.style.left = (caller.style.left+20) +'px'; 
    var foo = setTimeout('mve()', 2000); 
} 

발신자의 가치를 보존하는 전역 범위의 변수를 만들어서 보존 할 수 있습니다. li 요소의 id를 전달한 다음 getElementById()를 대신 호출하여 코드를 훨씬 더 명확하게 작성할 수 있습니다. 또는 jQuery를 사용하고 대신 $ ("# id") 구문을 사용하십시오.

+0

jfriend00의 답변에 따라 폐쇄 장치를 사용하는 클리너. – RobG