클로저는 JavaScript에서 중요한 기능이며 가장 큰 기능은 기능 작동 중에 정보를 저장하는 것입니다. JavaScript에서는 기능 호출 중 많은 클로저 기능이 범위 체인에서 파생됩니다.
함수의 범위 체인 호출 객체 및 변수
JavaScript의 각 함수 호출에 대해 JavaScript는 함수에 정의 된 로컬 변수를 저장하는 로컬 객체를 만듭니다. 함수 내에 중첩 된 기능이있는 경우 JavaScript는 이미 정의 된 로컬 객체에서 중첩 된 로컬 객체를 정의합니다. 함수의 경우 중첩 된 로컬 객체의 층이있는만큼 중첩 된 기능 정의의 층이 많이 있습니다. 이 로컬 객체를 "함수 호출 객체"(ECMAScript 3의 "Call Object"라고하며 ECMAScript 5에서 "선언 환경 레코드"로 이름이 바뀌었지만 개인적으로 ECMAScript 3의 이름을 이해하기가 더 쉽다고 생각합니다). 다음 기능 호출은 예로 사용됩니다.
코드 사본은 다음과 같습니다.
함수 f (x) {
var a = 10;
a*x;
}
Console.log (F (6)); // 60
이 간단한 예에서는 f () 함수를 호출 할 때 JavaScript는 f () 함수의 호출 객체를 생성합니다 (f_invokeobj라고 부릅니다). f_invokeobj 객체에는 두 가지 속성이 있습니다 : a와 x; f ()가 실행되면 A 값은 10이고 x 값은 6이므로 최종 반환 결과는 60입니다. 그림은 다음과 같습니다.
함수 중첩이 있으면 JavaScript는 여러 기능 호출 객체를 생성합니다.
코드 사본은 다음과 같습니다.
함수 f (x) {
var a = 10;
a*g (x)를 반환합니다.
기능 g (b) {
반환 b*b;
}
}
Console.log (F (6)); // 360
이 예에서는 f () 함수를 호출 할 때 JavaScript는 f () 함수 (f_invokeobj)의 호출 객체를 생성하며, 이는 두 가지 속성 a와 x가 있고 값 a는 10이고 값 x는 6입니다. f ()를 실행할 때 JavaScript는 f () 함수에서 g () 함수를 구문 분석하고 정의하고 속성 B를 갖는 g () (g_invokeobj)의 호출 객체를 생성하고 값 b는 전달 된 매개 변수 x와 동일하므로 최종 반환 결과는 360입니다. 그림은 다음과 같습니다.
보시다시피, 함수 호출 객체는 체인을 형성합니다. 임베디드 함수 g ()가 실행 중이며 변수 값을 얻어야 할 때 가장 최근의 기능 호출 객체에서 검색을 시작합니다. 검색 할 수없는 경우, 소위 "변수의 범위 체인"인 함수 호출 객체 체인을 따라 추가 호출 객체를 검색하십시오. 두 함수 호출 객체에 동일한 변수가 나타나면 함수가 가장 가까운 통화 객체의 변수 값을 취합니다.
코드 사본은 다음과 같습니다.
함수 f (x) {
var a = 10;
a*g (x)를 반환합니다.
기능 g (b) {
var a = 1;
B*B*A를 반환합니다.
}
}
Console.log (F (6)); // 360, 3600이 아닙니다
위의 예에서 변수 A는 g () 함수의 호출 객체 (g_invokeobj)와 f () 함수의 호출 객체 (f_invokeobj)에 다른 값을 갖습니다. g () 함수를 실행할 때 G () 함수 내에서 사용 된 A의 값은 1이고, g () 함수 외부에서 사용 된 값은 1입니다.이 시점의 함수 호출 객체 체인은 다음과 같습니다.
폐쇄 란 무엇입니까?
JavaScript의 모든 함수는 객체이며 함수를 정의 할 때 해당 기능 체인 객체가 생성됩니다. 함수 정의는 객체를 호출하는 함수 체인에 해당합니다. 함수 객체가 존재하는 한 해당 함수 호출 객체가 존재합니다. 함수가 더 이상 사용되지 않으면 해당 기능 호출 객체가 수집됩니다. 그리고이 함수 객체와 함수 콜 콜 객체의 조합을 "클로저"라고합니다. 위의 F () 함수 및 g () 함수의 위의 예에는 두 가지 클로저가 있습니다 : f () 함수 객체와 f_invokeobj 객체는 클로저를 형성하고 g () 함수 객체와 g_invokeobj-f_invokeobj 객체 체인은 두 번째 폐쇄를 형성합니다. g () 함수가 실행될 때, g () 함수가 더 이상 사용되지 않기 때문에 g () 클로저는 쓰레기가 수집됩니다. 그런 다음 f () 함수가 실행되면 F () 폐쇄도 같은 이유로 수집됩니다.
폐쇄의 정의에서 우리는 결론을 도출 할 수 있습니다. 모든 JavaScript 함수는 모든 함수가 객체이기 때문에 정의 후 폐쇄입니다. 모든 함수에는 실행 후 해당 통화 객체 체인이 있습니다.
그러나 폐쇄가 실제로 작동하는 것은 중첩 된 기능의 경우입니다. 임베디드 함수는 외부 함수가 실행될 때만 정의되므로, 임베디드 함수의 폐쇄에 저장된 변수 값 (특히 외부 함수의 로컬 변수 값) 이이 실행 중 값입니다. 임베디드 기능 객체가 여전히 존재하는 한, 폐쇄는 여전히 존재하므로 (폐쇄의 변수 값은 변경되지 않습니다) 함수 실행 프로세스의 정보를 저장하는 목적을 달성합니다. 다음 예를 고려하십시오.
코드 사본은 다음과 같습니다.
var a = "외부";
함수 f () {
var a = "내부";
함수 g () {return a;}
g;
}
var result = f ();
console.log (result ()); // 내부
이 예에서는 f () 함수가 실행되면 g () 함수가 정의되고 g () 함수의 폐쇄가 생성됩니다. g () 클로저에는 g_invokeobj-f_invokeobj 객체 체인이 포함되어 있으므로 f () 함수 실행 중 변수 a의 값이 저장됩니다. Console.log () 문이 실행되면 G () 객체가 여전히 존재하기 때문에 G () 폐쇄는 여전히 존재합니다. 이 여전히 존재하는 G 함수 객체를 실행할 때 JavaScript는 여전히 기존 G () 폐쇄를 사용하고 변수 a ( "내부")의 값을 가져옵니다.