이전 기사에서 우리는 사전 탐험에 대한 개요를 주었다. 이 블로그 게시물을 작성하기 전에 몇 가지 고전적인 사례를 작성할 계획이었습니다. 이러한 사례가 더 포괄적이라는 점을 고려할 때, 우리는이 블로그 게시물을 단계별로 가지고 있으며, 이는 학습하기 쉽고 심층적 인 JavaScript입니다.
순서
한 동료가 인터뷰에 갔고 면접관이 질문을했습니다. 문을 닫고 읽을 것입니까? 그래서 내 동료는 다음 코드를 빠르게 작성했습니다.
코드 사본은 다음과 같습니다.
함수 fn () {
ALERT ( 'Hello JavaScript Closure !!!'); // 젠장, e 텍스트는 좋지 않습니다. 번역을 찾은 후에 만 클로저 단어 만 쓸 수 있습니다.
}
fn ();
그런 다음 면접관은 고개를 저으며 말했다. 결국, 두 사람은 분쟁이 있었고 동료는 결정적으로 떠났습니다. 면접관의 일은 무엇입니까? (이 이야기는 순전히 허구입니다. 유사성이 있다면 순전히 우연의 일치입니다)
클로즈는 많은 사람들의 눈에서 "고급 및 어려운"기술 일 수 있지만 많은 사람들의 눈에는 클로저로 간주 될 수 있습니다.
Example 1:
코드 사본은 다음과 같습니다.
함수 fn () {
return function () {
경고 ( '예 1');
}
}
fn () ();
예 1 PS :이 사람은 그다지 진보되지 않은 것처럼 보이지 않습니다.이 사람은 그다지 좋지 않은 것 같습니다!
Example 2:
코드 사본은 다음과 같습니다.
;(기능 () {
경고 ( '예제 2');
}) ();
예 2 PS : 이것은 이전 것보다 더 발전된 것처럼 보이며 첫 번째 괄호 앞에 세미콜론이 있습니다. 세미콜론을 추가하는 이유는 무엇입니까? 글쎄,이 질문을 먼저 여기에두고 나중에 이야기하겠습니다.
Example 3:
코드 사본은 다음과 같습니다.
~ 함수 fn () {
경고 ( '예 3')
} ();
예 3 PS : 이것은 가장 진보 된 것입니다. 정말 놀랍습니다. 나는 덜 읽고, 나에게 거짓말하지 마십시오!
Lun의 주인은 독서에 능숙하지 않으며이 세 가지 "폐쇄"만 쓸 수 있습니다. 나는 블로거들이 점점 더 나은 "폐쇄"를 쓸 수 있다고 믿는다. 여기서 먼저 말도 안되는 일을 일시 중지 한 다음 기능 작동 메커니즘을 연구하십시오. 누군가가 이미 그것을 알고있는 것 같습니다. 범위가되어야합니다. 나는이 범위를 제목에 추가하고 싶지 않기 때문에 항상 그것이 거의 의미가 있다고 생각합니다. 이것들은 원래 함께 이루어 지므로 왜 반복해야합니까? 오래된 습관, 먼저 코드를 업로드하십시오.
코드 사본은 다음과 같습니다.
var n = 10;
함수 fn () {
경고 (n);
var n = 9;
경고 (n);
}
fn ();
간단히 말해서, 우리는 그림을 그립니다 (마스터는 Windows와 함께 제공되는 드로잉 소프트웨어 만 사용합니다. 더 나은 것이 있으면 블로거에게 권장하십시오).
분석 1
그림에서, 우리는 두 개의 스코프를 볼 수 있습니다. 하나는 창 범위 (최상위 범위)이고, 다른 하나는 FN이라고 불릴 때 형성된 개인 스코프입니다. 그렇다면 스코프 란 무엇입니까? 범위는 실제로 코드 실행 환경입니다. 예를 들어, 학생의 학습 환경은 학교이며, 그의 범위와 동일합니다. 학생이 장난 꾸러기이고 종종 밤에 게임을하기 위해 인터넷 카페에 가면 인터넷 카페인 개인 환경을 형성하는 것과 같습니다. 괜찮은! 이 Lizi는 그녀가 주인처럼 보일 때까지 너무나 도와 줄 수는 없지만 한숨을 쉬게 할 수는 없습니다. "어릴 때 열심히 일하지 않으면 자라면서 쫓겨날 것입니다." 주제로 돌아가 봅시다. 실제로 함수 FN의 정의는 코드 조각 (그림의 빨간색 상자)의 설명을 나타냅니다. 이 FN이 (그림의 녹색 상자) 호출되면 범위가 형성됩니다. 물론,이 범위의 코드는 실행 전에 미리 설명합니다. 실행 후이 범위가 파괴 될 것이라고 말하지 않을 것입니다. 이 FN은 다시 호출되며 새로운 범위를 형성 한 다음 실행하기 전에 사전 탐색 한 다음 코드 실행을 한 다음 실행 후에는 파괴됩니다.
폐쇄를 이해합니다
함수가 호출되면 개인 범위 (실행 환경)가 개인 스코프 (실행 환경)를 형성 하고이 개인 스코프는 폐쇄임을 알고 있습니다. 되돌아 보면, 폐쇄는 여전히 전설적인 "하이 엔드이고 쉽게 켜기가 쉽지 않다"고? 첫 번째 인터뷰 이야기와 내가 쓴 세 가지 예는 실제로 폐쇄입니다. 정확히 말하면,이 세 가지 예는 일반적인 형태의 폐쇄입니다.
응용 프로그램 시나리오
이제 요구 사항이 있습니다. HTML 페이지에는 UL 태그가 있으며 UL에는 5 개의 LI 태그가 있습니다. LI를 클릭해야하며 클릭 된 LI가 팝업되는 인덱스 (인덱스가 0부터 시작)가 필요합니다. HTML 구조는 다음과 같습니다.
코드 사본은 다음과 같습니다.
<ul id = "ul">
<li> 목록 1 </li>
<li> 목록 2 </li>
<li> 목록 3 </li>
<li> 목록 4 </li>
<li> 목록 5 </li>
</ul>
나는 똑똑했고 다음 코드를 빨리 썼습니다.
코드 사본은 다음과 같습니다.
var lis = document.getElementById ( 'ul'). getElementsByTagName ( 'li');
for (var i = 0, len = lis.length; i <len; i ++) {
lis [i] .onclick = function () {
경고 (i);
};
}
이 요구 사항이 완벽하게 구현되었는지 확인하기위한 최종 테스트 :
몇 번 클릭했는지에 관계 없이이 결과는 결국 나타날 것임을 알았습니다. 원하는 결과는 다음과 같습니다. 목록 1을 클릭하여 0을 팝업하고, 목록 2를 클릭하여 1 팝업 1을 클릭하고, 목록 3을 클릭하여 2 팝업 2 ...이 순간 에이 사진을 사용하여 현재 분위기를 설명하고 싶습니다.
(프로토 타입이 데모 중에 설계 요구 사항으로 실행되지 않을 때 어떻게 생겼습니까?)
어떻게해야하나요? 5가 항상 팝업되는 이유는 무엇입니까? 이론적으로는 매우 정확합니다! 분석 할 그림을 그리겠습니다.
실제로, 우리는 단지 각 li onclick을 제공합니다. 이것은 실제로 저장하는 함수 설명 문자열입니다. 이 문자열의 내용은 위의 그림의 빨간색 상자에있는 내용입니다. 당신이 여전히 그것을 믿지 않는다면, 나는 그림과 진실을 가지고 있습니다.
입력 : LIS [4]. Chrome 콘솔에서 클릭하면 그 값은 기능에 대한 설명입니다. 다섯 번째 목록을 클릭하면 실제로 LIS [4] .onclick ()과 동일합니다. 이 기능 설명을 호출 한 후에는 함수가 실행되면 개인 스코프가 형성된다는 것을 알고 있습니다. 이 개인 범위에서는 먼저 사전 설명 된 다음 코드가 실행됩니다. 이때 우리는 i를 찾을 것입니다. 현재의 개인 범위 아래에 내가없고, 창 범위 아래에서 내가 찾을 수 있으므로 클릭 할 때마다 5가 팝업됩니다.
분명히 위의 코드는이 요구 사항을 충족 할 수 없습니다. 코드를 작성하는 것이 잘못되었습니다. 문제의 이유에 대해 생각해 봅시다. 사실, 그 이유는 클릭 할 때마다 창문 아래 I에서 읽히기 때문입니다. 현재이 값은 이미 5이므로 다음 코드를 사용할 수 있습니다.
방법 1 : 방법 1
코드 사본은 다음과 같습니다.
var lis = document.getElementById ( 'ul'). getElementsByTagName ( 'li');
기능 fn (i) {
return function () {
경고 (i);
}
}
for (var i = 0, len = lis.length; i <len; i ++) {
lis [i] .onclick = fn (i);
}
방법 2 : 방법 2.
코드 사본은 다음과 같습니다.
var lis = document.getElementById ( 'ul'). getElementsByTagName ( 'li');
for (var i = 0, len = lis.length; i <len; i ++) {
; (기능 (i) {
lis [i] .onclick = function () {
경고 (i);
};
})(나);
}
메소드 3 :
코드 사본은 다음과 같습니다.
var lis = document.getElementById ( 'ul'). getElementsByTagName ( 'li');
for (var i = 0, len = lis.length; i <len; i ++) {
lis [i] .onclick = function fn (i) {
return function () {
경고 (i);
}
}(나);
}
나는 한 번의 호흡으로 세 가지 방법을 썼고 아이디어는 동일하며,이 변수 I을 개인 변수에 저장하는 것입니다. 여기서 나는 방법 2에 대해서만 이야기 할 것이다. 물론, 당신이 그들 중 하나를 이해한다면, 당신은 나머지를 이해할 것입니다. 컨벤션에 따르면, 그림을 그리고 단계별로 분석 해 봅시다.
전체 코드 실행에 대해 자세히 설명했습니다. 각 Li의 onclick 속성은 (함수 (i) {…}) (i) 범위를 점유해야한다는 점에 유의해야합니다. 이 함수가 실행되면 외부 Li (이 Li는 창 범위 아래에 있음)에 의해 점유되어 있기 때문에 파괴되지 않으므로이 범위는 파괴되지 않습니다. li를 클릭 할 때 function () {alert (i); }가 실행되고 범위도 형성됩니다. 이 범위에는 i가 없습니다. (function () {…}) (i)로 이동하여 i를 찾을 수있는 범위로 이동하고 마지막으로 공식 매개 변수에서 i를 찾을 수 있으며,이 공식 매개 변수의 값은 for 루프 동안 전달됩니다. 이 예제는 클로로 클로저를 사용하여 값을 저장하여 문제를 완벽하게 해결합니다.
추신 : 방금 (기능 (i) {…}) (i) 세미콜론을 그 앞에 추가 한 이유는 이전 진술이 세미콜론을 추가하는 것을 잊지 않도록하는 것입니다. 물론 위의 응용 프로그램 시나리오 중 하나는 탭 구현 원리입니다. 사용자 정의 속성 메소드 및 DOM 노드 관계를 통한 인덱스 찾기와 같은 다른 구현 방법이있을 수 있습니다. 마스터는이 방법을 채택하여 폐쇄에 대한 이해를 심화시킵니다.
요약
폐쇄는 전설적인 것만 큼 키가 크지 않습니다. 핵심은 기능 정의와 호출을 이해하는 것입니다. 함수가 호출되면 새로운 개인 범위가 형성됩니다. 범위가 외부에 의해 점유되면 범위는 파괴되지 않습니다. 루의 마스터는 거의 읽지 않습니다. 잘못된 것이 있으면 블로거로 나를 바로 잡으십시오. 동시에 누가의 마스터 기사를 지원해 주셔서 감사합니다.