소개
클로저는 다른 함수 범위에서 변수에 액세스 할 수있는 권한이있는 함수입니다.
폐쇄는 JavaScript에서 이해하기 어렵습니다. 많은 고급 응용 프로그램은 폐쇄에 의존하여이를 구현합니다. 먼저 아래 예를 살펴 보겠습니다.
함수 외부 () {var i = 100; 함수 내부 () {console.log (i); }}위의 코드에서 변수의 범위에 따라 함수 외부의 모든 로컬 변수는 함수 내부로 표시됩니다. 함수 내부의 로컬 변수는 함수 내부 외부에서 보이지 않으므로 함수 내부의 로컬 변수는 함수 내부 외부에서 읽을 수 없습니다.
내부가 내부가 반환 값으로 사용되는 한 함수 내부는 기능 외부의 로컬 변수를 읽을 수 있으므로 내부 로컬 변수는 OUER 외부에서 직접 읽을 수 있습니다.
함수 외부 () {var i = 100; 함수 내부 () {console.log (i); } return 내부;} var rs = outer (); rs ();이 기능에는 두 가지 특성이 있습니다.
이러한 방식으로 var rs = outer ()를 실행 한 후 실제 RS는 함수 내부를 가리 킵니다. 이 코드는 실제로 폐쇄입니다. 즉, 함수 내부의 내부 기능 외부 기능이 외부 외부의 변수로 참조되면 폐쇄가 생성됩니다.
범위
간단히 말해서, 범위는 접근 가능한 변수 및 함수 범위, 즉 범위는 변수 및 함수의 가시성 및 수명주기를 제어합니다. JavaScript에서 변수의 범위는 전역 및 로컬입니다.
글로벌 범위
var num1 = 1; function fun1 () {num2 = 2;}위의 세 가지 객체 Num1, Num2 및 Fun1은 모두 글로벌 스코프입니다. 여기서는 끝에서 직접 할당을 정의하는 변수가 전역 범위를 갖는 것으로 자동으로 선언된다는 점에 유의해야합니다.
로컬 범위
function wrap () {var obj = "랩으로 싸여 있고 랩 외부는 직접 액세스 할 수 없습니다."; 함수 innerfun () {// 외부에 액세스 할 수 없습니다}}스코프 체인
JavaScript의 모든 것은 객체입니다. 이 객체에는 [[scope]] 속성이 있으며, 여기에는 함수에 의해 생성 된 범위에 객체 모음이 포함되어 있습니다. 이 컬렉션을 함수의 범위 체인이라고하며 함수에 의해 액세스 할 수있는 데이터를 결정합니다.
함수 추가 (a, b) {return a+b;}함수가 생성되면 [[scope]] 속성이 자동으로 글로벌 범위를 추가합니다.
var sum = 추가 (3,4);
함수가 호출되면 실행 컨텍스트라는 내부 개체가 작성됩니다. 이 객체 z는 함수가 실행될 때 환경을 정의합니다. 또한 식별자 해상도를위한 자체 스코프 체인이 있으며, 스코프 체인은 현재 실행중인 함수의 [[Scope]]에 포함 된 개체로 초기화됩니다.
기능 실행 중에 변수가 발생할 때마다 식별자 구문 분석 프로세스가 전달되어 데이터를 얻고 저장할 위치를 결정합니다. 이 프로세스는 스코프 체인의 헤드에서 시작됩니다. 즉, 활성 객체에서 동일한 이름의 식별자를 검색합니다. 발견되면이 식별자에 해당하는 변수를 사용하십시오. 찾을 수없는 경우 스코프 체인에서 다음 객체를 계속 검색하십시오. 모든 객체를 검색하면 (마지막 객체는 전역 객체 임) 발견되지 않으면 식별자는 정의되지 않은 것으로 간주됩니다.
폐쇄
클로저는 단순히 외부 변수에 액세스하는 기능입니다.
var Quo = function (status) {return {getStatus : function () {return status; }}}상태는 quo로 저장되며 객체를 반환 하고이 개체의 getstatus는 상태 변수, 즉 getStatus 함수가 외부 변수 상태에 액세스하는 것을 나타냅니다.
var newValue = quo ( 'string'); // newValue에 의해 NewValue.getStatus ()로 참조 된 익명 객체를 반환합니다. // quo의 내부 변수 상태에 액세스했습니다.
getStatus 메소드를 사용할 수없는 경우 Quo ( 'Sting') 후에 상태가 자동으로 재활용됩니다. 반환 된 익명 객체가 글로벌 객체에 의해 참조되고 익명 객체는 상태에 따라 달라지기 때문에 정확히 해제를 방지하기 때문입니다.
예:
// 오류 체계 var test = function (노드) {var i; for (i = 0; i <nodes.length; i ++) {nodes [i] .onclick = function (e) {alert (i); }}}익명 함수는 클로저를 생성하고 액세스하는 I는 외부 테스트 함수의 i이므로 각 노드는 실제로 동일한 i를 나타냅니다.
// 개선 솔루션 var test = function (노드) {var i; for (i = 0; i <nodes.length; i ++) {nodes [i] .onclick = function (i) {return function () {alert (i); }; }(나); }}각 노드는 이벤트에 바인딩됩니다. 이 이벤트는 매개 변수를 수신하고 즉시 실행되어 i를 통과합니다. 값으로 전달되므로 각 루프는 현재 i에 대한 새로운 백업을 생성합니다.
폐쇄의 역할
함수 외부 () {var i = 100; 함수 내부 () {console.log (i ++); } return 내부;} var rs = outer (); rs (); // 100rs (); // 101rs (); // 102위의 코드에서 Rs는 폐쇄 내부 기능입니다. RS는 총 3 번, 처음은 100, 두 번째는 101, 세 번째는 102입니다. 이는 기능 외부의 로컬 변수 I이 메모리에 유지되었으며 호출 될 때 자동으로 지우지 않았다는 것을 보여줍니다.
폐쇄의 목적은 외부 실행이 완료되고 반환 된 후, 폐쇄는 외부의 내부 기능의 실행이 외부의 변수에 의존하기 때문에 외부가 점유하는 메모리를 재활용하지 않는 JavaScript의 쓰레기 수집 메커니즘 (Grabage Collection)이 외부에서 재활용되지 않는다는 것입니다. (또 다른 설명 : 외부는 내부의 부모 함수이며, 내부는 글로벌 변수에 할당되어 내부가 항상 메모리에있게되며, 내부의 존재는 외부에 의존하고 일부 외부는 항상 메모리에 있고 통화가 완료된 후에는 쓰레기가 수집되고 재활용되지 않기 때문에 외부에 의존합니다).
폐쇄에는 함수 내의 모든 변수에 액세스 할 수있는 권한이 있습니다.
함수가 클로저를 반환하면 함수의 범위가 폐쇄가 존재하지 않을 때까지 메모리에 저장됩니다.
폐쇄 및 변수
스코프 체인 메커니즘으로 인해 폐쇄는 함수의 변수를 포함하는 마지막 값 만 얻을 수 있습니다. 다음 예를 참조하십시오.
함수 f () {var rs = []; for (var i = 0; i <10; i ++) {rs [i] = function () {return i; }; } return rs;} var fn = f (); for (var i = 0; i <fn.length; i ++) {console.log ( 'function fn [' + i + ']] () 반환 값 :' + fn [i] ());}함수는 배열을 반환합니다. 표면적으로는 각 함수가 자체 인덱스 값을 반환 해야하는 것 같습니다. 실제로, 각 함수는 10을 반환합니다. 이것은 첫 번째 함수의 스코프 체인이 함수 f의 활성 객체를 포함하고 동일한 변수 i를 나타 내기 때문입니다. 함수 f가 반환되면 변수 i의 값은 10입니다.이 시점에서 각 함수는 변수 i의 동일한 변수 객체를 저장합니다. 우리는 다른 익명 기능을 만들어서 예상대로 행동을 강요 할 수 있습니다.
함수 f () {var rs = []; for (var i = 0; i <10; i ++) {rs [i] = function (num) {return function () {return num; }; }(나); } return rs;} var fn = f (); for (var i = 0; i <fn.length; i ++) {console.log ( 'function fn [' + i + ']] () 반환 값 :' + fn [i] ());}이 버전에서는 배열에 직접 클로저를 할당하는 대신 익명 함수를 정의하고 익명 함수를 배열에 즉시 실행 한 결과를 할당합니다. 익명 함수에는 매개 변수 Num이 있습니다. 각 함수를 호출 할 때 변수 i를 통과합니다. 매개 변수는 값으로 전달되므로 변수 i는 매개 변수 Num에 복사됩니다. 이 익명 함수 내부에서는 Closure Accessing NUM이 생성되고 반환됩니다. 이러한 방식으로 RS 어레이의 각 함수에는 자체 NUM 변수 사본이 있으므로 다른 값을 반환 할 수 있습니다.
이 개체는 폐쇄 중입니다
var name = 'jack'; var o = {이름 : 'bingdian', getName : function () {return function () {return this.name; }; }} console.log (o.getName () () ()); // jackvar name = 'jack'; var o = {이름 : 'bingdian', getName : function () {var self = this; return function () {return self.name; }; }} console.log (o.getName () () ()); // Bingdian메모리 누출
함수 antaiLDHER () {var el = document.getElementById ( 'demo'); el.onclick = function () {console.log (el.id); }} 할액 핸들러 ();위의 코드는 EL 요소 이벤트 핸들러로서 폐쇄를 생성 하며이 클로저는 원형 참조를 만듭니다. 익명 함수가 존재하는 한, EL 참조의 수는 1 이상입니다.
함수 antaiLDHER () {var el = document.getElementById ( 'demo'); var id = el.id; el.onclick = function () {console.log (id); } el = null;} 할액 핸들러 ();변수 EL NULL을 설정하면 DOM 객체를 해석하고 메모리를 정상적으로 소비 할 수 있습니다.
블록 수준 범위를 모방합니다
모든 곱슬 버팀대 ({및}) 쌍에 설정된 명령문은 블록에 속하며, 이에 정의 된 모든 변수는 코드 블록 외부에서는 보이지 않으며 블록 레벨 스코프라고합니다.
(함수 () {// 블록 레벨 스코프}) ();폐쇄의 적용
함수에서 변수의 보안을 보호하십시오. 이전 예에서와 같이, 함수 내부만이 기능 외부에서 I에 액세스 할 수 있지만 다른 채널을 통해 액세스 할 수 없으므로 i의 보안을 보호합니다.
메모리에서 변수를 유지하십시오. 이전 예에서와 같이, 폐쇄로 인해, 함수의 I는 항상 메모리에 존재하므로 RS ()가 실행 될 때마다 추가됩니다.