>웹 프론트엔드 >JS 튜토리얼 >javascript_기본지식을 바탕으로 클로저의 기본을 공유합니다.

javascript_기본지식을 바탕으로 클로저의 기본을 공유합니다.

WBOY
WBOY원래의
2016-05-16 17:29:11968검색

독립적인 객체로서의 범위와 함수의 기본 개념을 잘 이해하고 있다면 클로저의 개념을 이해하고 실제 프로그래밍 실습에 적용하는 것은 꽤 쉬울 것입니다.

DOM 이벤트 처리 측면에서 대부분의 프로그래머는 이미 클로저를 사용하고 있습니다. 이 경우 브라우저에 내장된 JavaScript 엔진의 버그로 인해 메모리 누출 문제가 발생할 수 있습니다. 디버깅할 때 종종 혼란스러워집니다.
간단한 문장을 사용하여 JavaScript의 클로저 개념을 설명합니다. JavaScript에서 함수는 객체이고 객체는 속성의 모음이며 속성의 값은 객체가 될 수 있으므로 다음과 같이 정의하는 것이 자연스럽습니다. 함수 내의 함수 func 내부에 함수를 선언한 다음 함수 외부에서 inner를 호출하면 클로저가 생성됩니다.
클로저의 특성:
먼저 예제를 살펴보겠습니다. JavaScript의 특성을 이해하지 못하면 이유를 찾기가 어렵습니다.

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

var outter = [];
function clouseTest() {
var array = ["1", " 2", "3", "4"];
for (var i = 0; i < array.length; i ) {
var x = {};
x.no = i;
                                                             Outter.push(x);
}
}
                                                                                     > ~                                         ; 많은 초보자들이 다음과 같은 대답을 할 수 있습니다:

0
1
2
3

그러나 이 프로그램을 실행하면 결과는 다음과 같습니다.

4
4
4
4 실제로 각 반복마다 x.invoke = function(){print(i);} 문은 실행되지 않고 함수 개체만 구성합니다. 함수 본문에 "print(i);"가 있으면 그게 전부입니다. i=4이면 반복이 중지되고 외부 함수가 반환됩니다. external[0].invoke()가 다시 호출되면 i 값은 여전히 ​​4이므로 외부 배열의 각 요소를 호출하면 i 값이 반환됩니다. . :4. 이 문제를 해결하는 방법? 익명 함수를 선언하고 즉시 실행할 수 있습니다.



코드 복사

코드는 다음과 같습니다.

var outter = [];
function clouseTest2() {
var array = ["one", "two", " three", "four"];
for (var i = 0; i < array.length; i ) {
var x = {};
x.no = i;
x.text = array[i];
x .invoke = 기능(아니요) {
                                                                                     ;
outter.push(x);
}
    }
    clouseTest2();
  


이 예에서는 x.invoke에 값을 할당할 때 먼저 함수를 반환할 수 있는 함수를 실행한 다음 즉시 실행합니다. 이런 식으로 x.invoke의 각 반복자는 다음과 같은 문을 실행하는 것과 같습니다. 이:


코드를 복사하세요 코드는 다음과 같습니다://x == 0
x.invoke = function(){print(0);}
//x == 1
x.invoke = function(){print(1);}
//x = = 2
x.invoke = function(){print(2);}
//x == 3
x.invoke = function(){print(3);}


이렇게 하면 올바른 결과를 얻을 수 있습니다. 클로저를 사용하면 외부 함수 내에 존재하는 변수를 참조할 수 있습니다. 그러나 변수가 생성되었을 때의 값을 사용하지 않고 대신 외부 함수에서 변수의 마지막 값을 사용합니다.
폐쇄의 목적:

이제 폐쇄의 개념이 명확해졌으니, 폐쇄의 목적을 살펴보겠습니다. 실제로 클로저를 사용하면 많은 일을 할 수 있습니다. 예를 들어, 객체 지향 코딩 스타일을 시뮬레이션할 수 있으며, 코드를 더욱 우아하고 간결하게 표현하고 일부 측면에서 코드의 실행 효율성을 향상시킵니다.
캐시:
또 다른 예를 살펴보겠습니다. 처리 시간이 매우 오래 걸리는 함수 개체가 있다고 가정해 보겠습니다. 계산 나오는 값은 저장되며, 이 함수가 호출되면 먼저 캐시에서 검색하여 찾지 못한 경우에는 캐시를 업데이트하고 찾은 경우 해당 값을 반환합니다. 찾은 값이 직접 반환됩니다.
클로저는 외부 참조를 해제하지 않고 함수 내부의 값을 유지할 수 있기 때문에 정확하게 이를 수행할 수 있습니다.


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

var CachedSearchBox = (함수 () {
var 캐시 = {},
count = [];
return {
attachmentSearchBox: 함수 (dsid ) {
                            ( dsid) {//결과가 캐시에 있는 경우
                                                                                 | 🎜>                   캐시[dsid] = fsb;//캐시 업데이트
                                                캐시 삭제[count.shift() ];
                                                                                                                                 ;                  if (캐시 내 dsid) {
                               ~ >     ;
var obj2 = CachedSearchBox .attachSearchBox("input1");



캡슐화 구현 :





코드 복사


코드는 다음과 같습니다.

var person = function( ){
//변수 범위는 함수 내부에 있으므로 외부에서 접근할 수 없습니다. var name = "default"
return {
}();

print(person.name );//직접 액세스, 결과는 정의되지 않음
print(person.getName());
person.setName("jack") ;
print(person.getName());



결과는 다음과 같습니다.

정의되지 않음
default
jack

클로저의 또 다른 중요한 용도는 객체 지향으로 객체를 구현하는 것입니다. 전통적인 객체 언어는 클래스 템플릿 메커니즘을 제공하므로 서로 다른 객체(클래스의 인스턴스)가 서로 간섭하지 않고 독립적인 멤버와 상태를 갖습니다. JavaScript에는 클래스와 같은 메커니즘이 없지만 클로저를 사용하여 이러한 메커니즘을 시뮬레이션할 수 있습니다. 위의 예를 들어보겠습니다.




코드 복사

코드는 다음과 같습니다.

function Person(){
var name = "default";

return {
getName : function(){
return name;
},
setName: function(newName){
name = newName;
}
}
};
var john = Person();
print(john.getName()) ;
john.setName("john");
print(john.getName());

var jack = Person();
print(jack.getName());
jack.setName("jack");
print(jack.getName());

실행 결과는 다음과 같습니다.
default
john
기본

JavaScript 클로저에서 주의해야 할 문제:
1. 메모리 누수:
다른 JavaScript 인터프리터 구현에서는 인터프리터 자체의 결함으로 인해 클로저로 인해 메모리 누수가 발생할 수 있습니다. 메모리 누수는 브라우저의 응답 속도에 심각한 영향을 미치고 사용자 경험을 저하시키며 심지어 브라우저가 응답하지 않게 만드는 심각한 문제입니다. JavaScript 인터프리터에는 일반적으로 참조 계산 형식을 채택하는 가비지 수집 메커니즘이 있습니다. 객체의 참조 카운트가 0이면 가비지 수집 메커니즘이 이를 재활용합니다. 그러나 클로저 개념을 사용하면 이 프로세스가 복잡해집니다. 나중에 로컬 변수를 사용해야 할 수도 있으므로 가비지 수집 메커니즘은 이러한 외부 참조를 처리하지 않습니다. , 객체 A는 B를 참조하고, B는 C를 참조하고, C는 A를 참조하는 경우, 이러한 상황은 가비지 수집 메커니즘에서 해당 참조 횟수가 0이 아니라고 결론을 내리게 되어 메모리 누수가 발생합니다.

2. 상황별 참조:

코드 복사 코드는 다음과 같습니다. 🎜>
$(function(){
var con = $("div#panel");
this.id = "content";
con.click(function() {
Alert(this.id);//panel
});
});

여기서 Alert(this.id)는 어떤 값을 의미하나요? 많은 개발자들이 클로저의 개념에 따라 잘못된 판단을 내릴 수 있습니다:

content
this.id에는 클릭 콜백에 표시되는 값이 할당되어 클로저가 이를 참조하게 됩니다. .id이므로 반환 값은 content입니다. 그러나 실제로 이 경고는 "패널"을 팝업으로 표시합니다. 클로저가 로컬 변수를 참조할 수 있지만 호출 개체의 존재로 인해 상황이 약간 미묘해집니다. 클로저가 호출되면(이 패널의 클릭 이벤트가 발생할 때) 여기서는 jQuery 개체 con을 참조합니다. 익명 함수의 this.id = "content"는 익명 함수 자체에 대해 수행되는 작업입니다. this 참조 두 개는 동일한 개체를 참조하지 않습니다.

이벤트 핸들러에서 이 값에 액세스하려면 다음과 같이 몇 가지 사항을 변경해야 합니다.
코드 복사 코드는 다음과 같습니다.
$(function(){
var con = $("div#panel");
this.id = "content" ;
var self = this;
con.click(function(){
Alert(self.id);//content
});
});

이런 식으로 우리가 이벤트 처리 함수에 저장하는 것은 this가 아닌 외부 로컬 변수 self에 대한 참조입니다. 이 기술은 많은 실제 적용이 가능하며 다음 장에서 자세히 논의할 것입니다. 클로저에 대해서는 다른 명령형 언어에서의 "클로저" 논의, 실제 프로젝트에서의 클로저 적용 등을 포함하여 9장에서 자세히 논의할 것입니다.

첨부: 제 수준의 한계로 인해 글에 누락이나 오류가 있을 수 있으며, 언어 자체가 부적절할 수 있으니 시기적절한 수정과 제안을 환영합니다. 이 기사는 다른 사람들에게 영감을 주기 위한 것입니다. 모두 감사합니다!
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.