클로저는 다른 함수의 범위에 있는 변수에 액세스할 수 있는 권한을 갖는 함수를 말합니다. 그러나 범위 구성 메커니즘에 대해 주의할 점이 하나 있습니다. 즉, 클로저는 모든 함수의 마지막 값만 얻을 수 있습니다. 포함하는 함수의 변수입니다.
다음과 같은 경우:
function create(){ var arr = new Array(); for (var i=0; i<10; i++){ arr[i] = function(){ return i; }; } return arr; } var c_arr = create(); for(var i=0; i<c_arr.length;i++){ document.write("c_arr["+i+"] = "+c_arr[i]()+"<br />"); }
실행 결과:
표면적으로는 각 함수에서 반환하는 i 값이 다른 것처럼 보입니다. 예를 들어 c_arr[0]의 값은 0이어야 하고, c_arr[1]의 값은 1이어야 하는 식입니다. 결과적으로 각 함수는 10을 반환합니다. 왜?
create() 함수의 활성 개체는 각 함수의 범위 체인에 저장되므로 모두 동일한 변수 i를 참조합니다. for 루프가 끝나면 i의 값은 10이 된다. 이때 각 함수는 변수 i를 담고 있는 동일한 변수 객체를 참조한다.
각 위치가 해당 값에 해당하도록 또 다른 도메인 이름 함수를 생성하여 클로저가 예상대로 작동하도록 강제할 수 있습니다.
function create(){ var arr = new Array(); for (var i=0; i<10; i++){ arr[i] = function(num){ return function(){ return num; }; }(i); } return arr; } var c_arr = create(); for(var i=0; i<c_arr.length;i++){ document.write("c_arr["+i+"] = "+c_arr[i]()+"<br />"); }
실행 결과:
익명 함수가 정의되고 익명 함수를 실행하는 메커니즘이 즉시 배열에 할당됩니다. 여기서 익명 함수에는 최종 함수에서 반환할 값인 num 매개변수가 있습니다. 각 함수를 호출할 때 변수 i를 전달합니다. 함수 매개변수는 값으로 전달되므로 변수 i의 현재 값이 매개변수 num에 할당됩니다. 이 익명 함수 내에서 num에 액세스하는 클로저가 생성되고 반환됩니다. 이러한 방식으로 arr 배열의 각 함수는 자체 num 변수의 복사본을 가지므로 다른 값을 반환할 수 있습니다.
전형적인 예
페이지에 버튼 태그 세트가 있다고 가정하고, 클릭 이벤트를 이 버튼 태그 세트에 바인딩하고, 클릭하면 몇 개의 태그가 팝업되는지 다시 살펴보겠습니다.
<meta charset="utf-8" /> <button>第一个</button> <button>第二个</button> <button>第三个</button> <button>第四个</button> <script type="text/javascript"> var obj = document.getElementsByTagName('button'); for(var i=0;i<obj.length;i++){ obj[i].onclick = function(){ alert(i); }; } </script>
각 버튼을 클릭하면 결과가 나옵니다
겉보기에는 각 라벨을 클릭하면 다른 번호가 나타나는 것처럼 보입니다.
첫 번째 항목은 0으로 표시되어야 합니다.
두 번째 항목은 1로 표시되어야 합니다.
등등.
하지만 결과적으로 모든 버튼이 4개로 팝업되는데, 이는 분명히 우리가 원하는 결과가 아닙니다.
프로그램을 바꾸자
<meta charset="utf-8" /> <button>第一个</button> <button>第二个</button> <button>第三个</button> <button>第四个</button> <script type="text/javascript"> var obj = document.getElementsByTagName('button'); for(var i=0;i<obj.length;i++){ obj[i].onclick = function(num){ return function(){ alert(num); } }(i); } </script>
두 번째를 클릭하세요
네 번째 항목을 클릭하세요
위의 경우와 마찬가지로 함수 내에 익명함수만 생성하면 됩니다. 외부 변수 i를 캡처하는 익명 함수를 구현할 수 있습니다. 결과적으로 각 버튼 폭탄의 i 값은 다릅니다.