2013-02-21 6 views
4

문제의 코드 사이의 상호 작용에 의해 혼란 :함수 파라미터, 클로저 및 범위 체인

function addLinks() { 
    for (var i=0, link; i<5; i++) { 
     link = document.createElement("a"); 
     link.innerHTML = "Link " + i; 
     link.onclick = function (num) { 
      return function() { 
       alert(num); 
      }; 
     }(i); 
     document.body.appendChild(link); 
    } 
    } 
    window.onload = addLinks; 

내 문제 복귀 함수는 폐쇄되고 가변 num 함수가 num을 실행할 때마다 전역 변수이기 때문에 이전 값을 현재 값으로 유지해야하며 모든 값을 자동으로 업데이트해야합니다. 그러나 이것은 일어나지 않습니다. 각 링크를 클릭하면 다른 가치를 얻습니다. 왜 이런 일이 일어나는 걸까요?

+0

문제점을 이해하지 못합니다. 콘솔에서'addLinks'의 첫 번째 버전을 실행 한 다음 추가하는 링크를 클릭하면 다른 값이 알려질 때마다 결과가 표시됩니다. 이 예기치 않은 행동이 있습니까? – marekful

+0

@Marcell Fülöp 예기치 않게 num이 전역 변수이고 해당 값이 함수가 실행될 때마다 변경되거나 업데이트되어야합니다. –

+1

@Maizere num은 전역이 아닙니다. 함수 매개 변수를 정의 할 때'var' 키워드가 필요하지 않습니다. 함수에 대해 암시 적으로 지역 변수입니다. – Dennis

답변

1

를 생각해 보라 : 당신은 세 가지 연결과 같이 무엇을했다 경우 :

<a href="#">0</a> 
<a href="#">1</a> 
<a href="#">2</a> 

당신은 그들에게 경고하려는 클릭 핸들러 그래서 나는 같이 그것을 시도 할 매개 변수로 이벤트 오브젝트를 그들의 숫자에서 당신은 그들을 클릭하면, 그래서 당신은 이런 식으로 작업을 수행합니다 언뜻

var links = $('a'); 
for (var i = 0; i < links.length; i++) { 
    links[0].onclick = function() { 
     alert(i); 
    } 
} 

, 당신은 당신이 때를 첫 번째 링크를 클릭 핸들러를 할당 예를 들어, 이후 것으로 기대을 클릭하면 0을 클릭하면 알려줍니다. 그러나이를 클릭하면 실제로는 3으로 알려줍니다.

당신이 말했듯이, 코드는 클로저를 만듭니다. 위의 코드는 각 링크의 click 이벤트에 함수 핸들러를 지정한다는 것입니다. 각 함수 핸들러는 변수 i에 대한 참조를 유지 관리합니다 (참고 : 현재 값이 아닙니다!).

함수 핸들러를 할당 할 시점에 실제로는 i의 값을 평가하지 않습니다 (필요하지 않으므로). 클릭하면, aha, 그게 i 값을 확인하고 경고합니다.

링크를 클릭하면 for 루프가 완료되고 i = 3으로 길게 완료되며 클릭 처리기에서이를 알립니다.

0

귀하의 기능 후에 (i)를보십시오. 이 유형의 표기}은 자체 호출 기능 전용입니다. 마치 link.onclick = 숫자를 설정하는 것과 같습니다. 반면에 함수를 기대합니다. 당신은 단순히 다음을 사용할 수 있습니다.

link.onclick = function (event) { 
     event.preventDefault(); 
     alert(i); 
    }; 

클릭 기능은 기본적으로 매개 변수로 '이벤트'를 수신합니다. 이벤트의 preventDefault() 메소드를 호출해야합니다. 그렇지 않으면 DOM을 버블 링하고 앵커 요소의 특성으로 인해 포스트 백이 트리거됩니다.

+0

무엇을 말하고 있습니까, U는 화제가 아닙니다. –

+0

"마치 link.onclick = 숫자를 설정하는 것 같습니다."아니오 - 그렇지 않습니다. 그것을 함수로 설정하십시오. –

2

num은 익명 기능으로 폐쇄됩니다. function (num) { return function() {}}(i)i을 그대로 내부 함수에 전달하고 i의 값이 당시 값일 때 새 함수를 반환합니다. 당신은 클릭 콜백은 항상 i의 최대 값을 경고하려는 경우

, 그것은 사실도 쉽게 :

link.onclick = function() { 
    alert(i); 
} 

function (var varname)은 단순히 잘못된 구문입니다.

0

변수 num의 출처 또는 사용 방법을 설명하지 않았습니다. i의 현재 값을 경고한다는 의미입니다.

function addLinks() { 
for (var i=0; i<5; i++) { 
    var link = document.createElement("a"); 
    link.innerHTML = "Link " + i; 
    link.onclick = function (event) { 
      alert(i); 
    }; 
    document.body.appendChild(link); 
} 
} 
window.onload = addLinks; 
+0

HTML 요소에는'.on' 메서드가 없습니다. – 0x499602D2

+0

네가 맞다. jQuery가 섞여있다. 내 사과. 그래서 당신은 그것을 되돌릴 수 link.onclick = function (event) {alert (i); }; 지적 해 주셔서 감사합니다 .-) – CSilivestru

0

이것은 이상하고 클로저에 대해 알고 있다고 생각하는 것에 동의하지 않습니다. (질문에 addLinks의 첫 번째 버전에서) 유일한 변화 :

link.onclick = function (num) 

link.onclick = function() 

에 당신은, 즉, 글로벌 num 변수의 실제 값이 경고되고 예상 된 결과를 얻을 수 언제든지 링크를 클릭하십시오.

아마도 클로저가 클로저를 만났을 때 클로저 내에서 참조되는 범위 변수를 인터프리터가 저장하는 방법과 관련이 있습니다. 변수가 클로저에서 참조 될 때, 해당 변수의 가장 가까운 어커런스가 현재 범위에서 위쪽으로 이동하도록 검색됩니다.

첫 번째 경우는 선언 후 여러 번이라고하는 이라는 함수에 대한 매개 변수로 정의되지만 매번 다른 값이 있으므로 각 범위 값이 각 클로저별로 "기억"됩니다.

두 번째 경우에서 발견 된 유일한 발생은 전체 범위에 있으며 이는 처리기가 호출되는 것과 관계없이 실제 값이 num 인 결과입니다.

관련 문제