1. 폐쇄란 무엇인가요?
"공식적인" 설명은 다음과 같습니다. 소위 "클로저"는 많은 변수와 이러한 변수에 바인딩된 환경이 있는 표현식(일반적으로 함수)을 의미하므로 이러한 변수도 다음의 일부입니다. 표현.
그의 설명이 너무 학문적이어서 이 문장을 직접적으로 이해하는 사람은 거의 없다고 생각합니다. 클로저 생성 과정을 건너뛰고 클로저의 정의를 직접 이해하는 것은 매우 어렵기 때문에 Javascript에서 클로저를 생성하는 방법을 사용하여 클로저가 무엇인지 알려드리고 싶습니다. 아래 코드를 보세요:
function a( ){
var i=0;
function b(){
alert( i);
}
return b;
}
var c = a();
c()
이 코드에는 두 가지 특성이 있습니다.
1. 함수 b는 함수 a 내에 중첩되어 있습니다.
2. 함수 a는 함수 b를 반환합니다.
이런 식으로 var c=a()를 실행한 후 변수 c는 실제로 함수 b를 가리킵니다. c()를 다시 실행하면 i의 값을 표시하는 창이 팝업됩니다(처음에는 1) . 이 코드는 실제로 클로저를 생성합니다. 이유는 무엇입니까? 함수 a 외부의 변수 c는 함수 a 내부의 함수 b를 참조하기 때문에, 즉 다음과 같습니다.
함수 a 내부의 함수 b가 함수 a 외부의 변수에 의해 참조되면 클로저가 생성됩니다.
클로저의 기능을 모르기 때문에 아직 클로저를 이해하지 못하는 것 같습니다.
2. 클로저 기능은 무엇인가요?
간단히 말해서 클로저의 기능은 a가 실행되고 반환된 후 a의 내부 기능으로 인해 Javascript의 가비지 수집 메커니즘 GC가 a가 점유한 리소스를 회수하는 것을 방지하는 것입니다. b의 변수는 a의 변수에 따라 달라집니다. 이는 클로저의 역할에 대한 매우 간단한 설명입니다. 전문적이거나 엄격하지는 않지만 일반적인 의미는 클로저를 이해하는 데에는 단계별 프로세스가 필요하다는 것입니다.
위의 예에서 클로저의 존재로 인해 a의 i는 함수 a가 반환된 후에 항상 존재하게 됩니다. 이런 식으로 c()가 실행될 때마다 i는 다음과 같은 i 값이 됩니다. 1을 추가한 후 경고를 받았습니다. .
그러면 a가 b가 아닌 다른 것을 반환한다면 상황은 완전히 달라집니다. 왜냐하면 a가 실행된 후 b는 a의 외부 세계로 반환되지 않고 a에 의해서만 참조되기 때문입니다. 이때 a는 b에 의해서만 참조됩니다. 따라서 함수 a와 b는 서로를 참조하지만 방해받지 않습니다. 외부 세계에서 참조됨), 함수 a 및 b는 GC에 의해 재활용됩니다. (자바스크립트의 가비지 컬렉션 메커니즘은 추후 자세히 소개하겠습니다.)
3. 클로저 안의 미시적 세계
클로저에 대해 더 깊이 이해하고 싶다면 함수 a와 중첩된 함수 b 사이의 관계에 대해서는 함수 실행 컨텍스트(실행 컨텍스트), 활성 객체(호출 객체), 범위(scope) 및 범위 체인(scope chain) 등 몇 가지 다른 개념을 도입해야 합니다. 이러한 개념을 설명하기 위해 정의부터 실행까지 함수 a의 프로세스를 예로 들어 보겠습니다.
1. 함수 a를 정의할 때 js 인터프리터는 함수 a의 범위 체인을 a를 정의할 때의 "환경"으로 설정합니다. a가 전역 함수인 경우 window 개체만 있습니다. 범위 체인에서.
2. 함수 a가 실행되면 a는 해당 실행 컨텍스트로 들어갑니다.
3. 실행 환경을 생성하는 과정에서 먼저 a의 범위인 a에 범위 속성이 추가되며 해당 값은 1단계의 범위 체인입니다. 즉, a.scope=a의 범위 체인입니다.
4. 그러면 실행 환경이 호출 개체를 생성합니다. 활성 개체도 속성은 있지만 프로토타입이 없고 JavaScript 코드에서 직접 액세스할 수 없는 개체입니다. 활성 개체를 만든 후 범위 체인의 맨 위에 활성 개체를 추가합니다. 이때 a의 범위 체인에는 a의 활성 개체와 창 개체라는 두 개체가 포함됩니다.
5. 다음 단계는 함수 a를 호출할 때 전달된 매개변수를 저장하는 활성 객체에 인수 속성을 추가하는 것입니다.
6. 마지막으로 함수 a의 모든 형식 매개변수와 내부 함수 b에 대한 참조를 a의 활성 개체에 추가합니다. 이번 단계에서는 함수 b의 정의가 완료되므로 3단계와 마찬가지로 함수 b의 스코프 체인은 b가 정의된 환경, 즉 a의 스코프에 설정된다.
이제 전체 함수 a의 정의부터 실행까지의 단계가 완료되었습니다. 이때 a는 함수 b의 참조를 c에 반환하고 함수 b의 범위 체인에는 함수 a의 활성 개체에 대한 참조가 포함되어 있습니다. 이는 b가 a에 정의된 모든 변수와 함수에 액세스할 수 있음을 의미합니다. 함수 b는 c에 의해 참조되고 함수 b는 함수 a에 종속되므로 함수 a는 반환 후 GC에 의해 재활용되지 않습니다.
b 함수가 실행되면 위의 단계와 동일합니다. 따라서 실행 중 b의 범위 체인에는 다음 그림과 같이 b의 활성 개체, a의 활성 개체 및 창 개체의 3개 개체가 포함됩니다.
그림과 같이 함수 b에 액세스할 때 a가 변수를 사용하는 경우 검색 순서는 자신의 활성 개체를 먼저 검색하고 존재하지 않으면 반환하는 것입니다. 존재하지 않으면 함수 a의 활성 개체를 계속 검색하고 해당 개체가 나올 때까지 순차적으로 검색합니다. 설립하다. 전체 범위 체인에서 찾을 수 없으면 정의되지 않은 값이 반환됩니다. 함수 b에 프로토타입 프로토타입 객체가 있는 경우 먼저 자체 활성 객체를 검색한 후 자체 프로토타입 객체를 검색한 다음 계속 검색합니다. 이것은 Javascript의 변수 조회 메커니즘입니다.
4. 클로저 적용 시나리오
1. 함수 내 변수를 보호하세요. 초기 예제를 예로 들면, 함수 a의 i는 함수 b를 통해서만 접근할 수 있고 다른 수단으로는 접근할 수 없으므로 i의 보안이 보호됩니다.
2. 메모리에 변수를 유지합니다. 이전 예제와 마찬가지로 클로저로 인해 함수 a의 i는 항상 메모리에 존재하므로 c()가 실행될 때마다 i는 1씩 증가합니다.
위의 두 가지 사항은 클로저의 가장 기본적인 적용 시나리오이며 많은 고전적인 사례가 여기에서 유래합니다.
5. Javascript의 가비지 수집 메커니즘
Javascript에서 객체가 더 이상 참조되지 않으면 해당 객체는 GC에 의해 재활용됩니다.두 객체가 서로를 참조하고 더 이상 제3자가 참조하지 않는 경우, 서로를 참조하는 두 객체도 재활용됩니다. 함수 a는 b에 의해 참조되고 b는 a 외부의 c에 의해 참조되기 때문에 함수 a는 실행 후 재활용되지 않습니다.