> 웹 프론트엔드 > JS 튜토리얼 > Javascript_기본 지식의 클로저에 대한 자세한 설명

Javascript_기본 지식의 클로저에 대한 자세한 설명

WBOY
풀어 주다: 2016-05-16 16:24:21
원래의
970명이 탐색했습니다.

머리말: 아직은 소개 글입니다. Javascript에는 객체, 프로토타입 상속 및 클로저와 같은 몇 가지 매우 중요한 언어 기능이 있습니다. 그 중 클로저(Closure)는 전통적인 정적 언어 C/C를 사용하는 프로그래머를 위한 새로운 언어 기능입니다. 이 기사는 Javascript 클로저의 언어 기능을 소개하는 예제로 시작하고 이를 일부 ECMAScript 언어 사양과 결합하여 독자가 클로저에 대해 더 깊이 이해할 수 있도록 합니다.

참고: 이 기사는 소개 기사입니다. 예제 자료는 인터넷에서 편집한 것입니다. 전문가라면 기사에 대한 기술적 제안과 의견을 제공하실 수 있습니다. 이 글은 자바스크립트에 대해 다루고 있습니다. 자바스크립트가 불편하신 분들은 우회하시기 바랍니다.

폐쇄란 무엇인가
클로저(Closure)란 정적 언어에는 없는 새로운 기능인 클로저(Closure is Closure)입니다. 하지만 클로저는 이해하기에는 너무 복잡한 것이 아닙니다. 간단히 말해서 클로저는

입니다.

클로저는 함수의 지역 변수 모음이지만 이러한 지역 변수는 함수가 반환된 후에도 계속 존재합니다.
클로저는 함수가 반환된 후에 함수의 "스택"이 해제되지 않음을 의미합니다. 또한 이러한 함수 스택은 스택에 할당되지 않고 힙에 할당된다는 점도 이해할 수 있습니다.
함수 내에서 다른 함수를 정의하면 클로저가 생성됩니다
위의 두 번째 정의는 첫 번째 보충 설명으로, 첫 번째 정의의 주어, 술어, 목적어를 추출한 것입니다. 클로저는 함수의 '지역 변수' 집합입니다. 단지 함수가 반환된 후에 이 지역 변수에 액세스할 수 있다는 것뿐입니다. (공식적인 정의는 아니지만 클로저를 이해하는 데 이 정의가 더 도움이 될 것입니다.)

로컬 변수이므로 함수 내의 코드로 액세스할 수 있습니다. 이는 정적 언어와 다르지 않습니다. 클로저와의 차이점은 함수 실행이 끝난 후에도 함수 외부의 코드를 통해 지역 변수에 계속 액세스할 수 있다는 것입니다. 이는 함수가 클로저를 가리키는 "참조"를 반환하거나 이 "참조"를 외부 변수에 할당하여 클로저의 지역 변수가 외부 코드에서 액세스될 수 있도록 해야 함을 의미합니다. 물론, 이 참조를 포함하는 엔터티는 객체여야 합니다. 왜냐하면 Javascript에서는 기본 유형을 제외한 모든 것이 객체이기 때문입니다. 안타깝게도 ECMAScript는 클로저의 지역 변수에 액세스하기 위한 관련 멤버와 메서드를 제공하지 않습니다. 하지만 ECMAScript에서는 함수 객체에 정의된 내부 함수(내부 함수)가 외부 함수의 로컬 변수에 직접 접근할 수 있습니다. 이 메커니즘을 통해 다음과 같은 방법으로 클로저에 대한 접근을 완료할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

함수 인사말(이름) {
var text = '안녕하세요' name; // 지역변수
// 호출될 때마다 클로저가 생성되고 내부 함수 객체가 호출자에게 반환됩니다.
반환 함수() { 경고(텍스트) }
}
var sayHello=greeting("폐쇄");
sayHello() // 지역 변수 text
는 클로저를 통해 액세스됩니다.

위 코드의 실행 결과는 Hello Closure입니다. 왜냐하면 sayHello() 함수는 인사말 함수가 실행된 후에도 그 안에 정의된 로컬 변수 텍스트에 계속 액세스할 수 있기 때문입니다.

이것은 클로저의 전설적인 효과입니다. 클로저는 Javascript에서 Singleton, Power Constructor 및 클로저 사용과 분리할 수 없는 기타 Javascript 모드와 같은 다양한 애플리케이션 시나리오와 모드를 가지고 있습니다.

ECMAScript 클로저 모델
ECMAScript는 클로저를 어떻게 구현합니까? 더 배우고 싶은 분들은 연구용 ECMAScript 사양을 얻으실 수 있습니다. 여기서는 간단한 설명만 드리고 내용도 인터넷에서 가져왔습니다.

ECMAscript 스크립트의 함수가 실행될 때 각 함수 연관에는 실행 컨텍스트 장면(Execution Context)이 있습니다. 이 실행 컨텍스트 장면은 세 부분으로 구성됩니다.

어휘 환경
가변환경
이 바인딩
세 번째 사항인 이 바인딩은 클로저와 관련이 없으며 이 기사에서는 논의하지 않습니다. 문법 환경은 함수 실행 중에 사용되는 변수 식별자를 구문 분석하는 데 사용됩니다. 우리는 문법 환경을 환경 레코드(Enviroment Recode)와 외부 참조(포인터)라는 두 가지 중요한 구성 요소를 포함하는 객체로 상상할 수 있습니다. 환경 레코드에는 함수 내부에 선언된 지역 변수와 매개변수 변수가 포함되어 있으며, 외부 참조는 외부 함수 개체의 컨텍스트 실행 시나리오를 가리킵니다. 전역 컨텍스트 장면에서 이 참조 값은 NULL입니다. 이러한 데이터 구조는 각 참조가 외부 컨텍스트 장면을 가리키는 단방향 연결 목록을 형성합니다.

예를 들어 위 예시의 클로저 모델은 다음과 같아야 합니다. sayHello 함수는 맨 아래 레이어에 있고, 맨 위 레이어는 인사말 기능이고, 가장 바깥쪽 레이어는 전역 장면입니다. 아래와 같이 sayHello가 호출되면 sayHello는 컨텍스트 장면을 통해 로컬 변수 텍스트의 값을 찾게 되므로 화면의 대화 상자에 "Hello Closure"가 표시됩니다. 변수 환경(The VariableEnvironment)의 기능. 문법 환경은 기본적으로 유사합니다. 구체적인 차이점은 ECMAScript 사양 문서를 참조하세요.

마감 순서 샘플
이전에는 Javascript 클로저가 무엇인지, Javascript에서 클로저가 어떻게 구현되는지 대략적으로 이해했습니다. 아래에서는 몇 가지 예를 통해 클로저에 대해 더 깊이 이해할 수 있도록 도와드리겠습니다. 아래에는 JavaScript Closures For Dummies(미러)에서 가져온 예가 있습니다. 예시 1: 클로저의 지역 변수는 복사본이 아닌 참조입니다.

코드 복사 코드는 다음과 같습니다.

함수 say667() {
// 클로저 내에서 끝나는 지역 변수
변수 번호 = 666;
var sayAlert = function() { 경고(숫자) }
숫자 ;
경고 메시지를 반환합니다.
}

var sayAlert = say667();
경고()라고 말하세요

따라서 실행 결과는 666이 아닌 667이 되어야 합니다.

예 2: 여러 함수가 동일한 함수에 정의되어 있으므로 동일한 클로저를 바인딩합니다.

코드 복사 코드는 다음과 같습니다.

함수 setupSomeGlobals() {
// 클로저 내에서 끝나는 지역 변수
변수 번호 = 666;
// 함수에 대한 일부 참조를 전역 변수로 저장합니다
gAlertNumber = function() { 경고(숫자) }
gIncreaseNumber = 함수() { 숫자 }
gSetNumber = 함수(x) { 숫자 = x }
}
setupSomeGlobals(); // 세 개의 전역 변수에 값을 할당합니다
g경고번호(); //666
gIncreaseNumber();
g경고번호(); // 667
gSetNumber(12);//
gAlertNumber();//12

예 3: 루프에 함수를 할당할 때 이러한 함수는 동일한 클로저에 바인딩됩니다

코드 복사 코드는 다음과 같습니다.

함수 buildList(목록) {
var 결과 = [];
for (var i = 0; i < list.length; i ) {
        var item = '항목' 목록[i];
result.push( function() {alert(item ' ' list[i])} );
}
결과 반환;
}
함수 testList() {
var fnlist = buildList([1,2,3]);
// 혼란을 방지하기 위해 j만 사용 - i를 사용할 수 있음
for (var j = 0; j < fnlist.length; j ) {
            fnlist[j]();
}
}

testList의 실행 결과 item3 정의되지 않은 창이 3번 팝업되는 것은 이 세 함수가 동일한 클로저에 바인딩되어 있고 item의 값이 마지막으로 계산된 결과이지만 루프에서 빠져나오면 i의 값은 4이므로 list [4]의 결과는 정의되지 않습니다.

예 4: 내부 함수가 정의된 후에 이 변수가 선언되더라도 외부 함수의 모든 지역 변수는 클로저 내에 있습니다.

코드 복사 코드는 다음과 같습니다.

함수 sayAlice() {
var sayAlert = function() { 경고(앨리스) }
// 클로저 내에서 끝나는 지역 변수
var alice = '안녕하세요 앨리스';
경고 메시지를 반환합니다.
}
var helloAlice=sayAlice();
안녕하세요앨리스();

실행 결과 "Hello Alice" 팝업창이 뜹니다. sayAlert 함수 이후에 지역 변수를 선언하더라도 해당 지역 변수에 계속 접근할 수 있습니다.

예 5: 함수가 호출될 때마다 새로운 클로저 생성

코드 복사 코드는 다음과 같습니다.

함수 newClosure(someNum, someRef) {
// 클로저 내에서 끝나는 지역 변수
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
반환함수(x) {
         숫자 = x;
        anArray.push(num);
Alert('숫자: ' 숫자
          'nanArray' anArray.toString()
          'nref.someVar ' ref.someVar);
}
}
closure1=newClosure(40,{someVar:'closure 1'});
closure2=newClosure(1000,{someVar:'closure 2'});

closure1(5); // 숫자:45 anArray[1,2,3,45] ref:'someVar closure1'
closure2(-10);// 숫자:990 anArray[1,2,3,990] ref:'someVar closure2'

폐쇄 신청
싱글톤:

코드 복사 코드는 다음과 같습니다.

var 싱글톤 = 함수 () {
var privateVariable;
함수 privateFunction(x) {
           ...private변수...
}

복귀 {
         firstMethod: 함수 (a, b) {
                  ...privateVariable...
},
secondMethod: 함수 (c) {
                  ...privateFunction()...
}
};
}();

이 싱글톤은 클로저를 통해 구현됩니다. 비공개 멤버 및 메소드의 캡슐화는 클로저를 통해 완료됩니다. 익명의 메인 함수는 객체를 반환합니다. 객체에는 두 가지 메서드가 포함되어 있습니다. 메서드 1은 전용 변수에 액세스할 수 있고, 메서드 2는 내부 전용 함수에 액세스할 수 있습니다. 주의가 필요한 것은 익명의 메인 함수 끝에 있는 '()'입니다. 이 '()'가 없으면 싱글톤이 생성될 수 없습니다. 익명 함수는 고유한 개체만 반환할 수 있고 다른 곳에서는 호출할 수 없기 때문입니다. 클로저를 사용하여 싱글톤을 생성하는 방법입니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿