[자 바스 크 립 트] 난점 2 - 클 로즈 드

패 킷 닫 기: 다른 함수 역할 영역 에 접근 할 수 있 는 변 수 를 말 합 니 다.패 킷 을 만 드 는 방식 은 한 함수 내부 에 두 개의 함 수 를 만 드 는 것 입 니 다. -'자 바스 크 립 트 고급 프로 그래 밍' 패 키 지 는 함수 내 부 를 포함 하 는 모든 변 수 를 방문 할 수 있 습 니 다. 원 리 는 다음 과 같 습 니 다. 배경 실행 환경 에서 패 키 지 를 닫 는 역할 도 메 인 체인 은 자신의 역할 도 메 인, 함수 내 부 를 포함 하 는 역할 도 메 인 과 전체 역할 도 메 인 을 포함 합 니 다.일반적으로 함수 의 역할 영역 과 모든 변 수 는 함수 실행 이 끝 난 후에 삭 제 됩 니 다. 그러나 함수 가 패 킷 을 되 돌 렸 을 때 이 함수 의 역할 영역 은 패 킷 이 존재 하지 않 을 때 까지 메모리 에 저 장 됩 니 다.이 말로 이해 하면 가방 을 닫 는 것 은 포 함 된 함수 이 잖 아!내장 함수 가 함 수 를 포함 하 는 변 수 는 당연히 접근 할 수 있 습 니 다. 이것 은 문제 가 없습니다.
면접 을 볼 때 자주 폐쇄 와 관련 된 질문 을 받 는데 폐쇄 가 무엇 입 니까?왜 폐쇄 를 사용 합 니까?최근 에 폐쇄 를 자세히 연 구 했 는데 지금 은 다음 과 같다.
1. 폐쇄 란 무엇 인가
function a(){  
    var name="vicky"; 
    console.log(name); 
} 
a();//vicky
            ,         ,         ,                  ,        。
function a(){  
    var name="vicky";  
    function show() {  
        console.log(name);  
    }  
    return show;  
}  
var func = a();  
func();//vicky

상기 코드 는 전형 적 인 패 킷 을 형성 하고 함수 a () 가 실 행 된 후에 도 내부 에서 설명 하 는 변수 name 을 사용 할 수 있 습 니 다.이렇게 두 단락 의 코드 는 물론 매우 까다롭다.먼저 역할 영역 체인 을 돌 이 켜 보 세 요:
역할 도 메 인 체인: 만약 에 우리 가 역할 도 메 인 을 간단하게 등급 으로 나 누 면 전체 역할 도 메 인 을 1 급 으로 가정 한다. 그 중에서 정 의 된 함수 체 내부 역할 도 메 인 을 2 급 으로 하고 2 급 역할 도 메 인 에 정 의 된 함수 체 내부 역할 도 메 인 을 3 급 으로 한다. 등등 전통 적 인 의미 에서 1 급 은 2 급 변수 (이런 변 수 를 부분 변수 라 고 함) 에 접근 할 수 없다.2 급 은 3 급 에 접근 할 수 없습니다. 반대로 가능 합 니 다. 이것 이 바로 역할 도 메 인 체인 입 니 다.이 급 역할 영역 에서 1 급 전체 국면 까지 더 이상 찾 을 수 없습니다.
폐쇄: 폐쇄 라 는 메커니즘 은 1 급 작용 역 에서 3 급 작용 역 을 통 해 2 급 작용 역 에서 변 수 를 인용 할 수 있다. 방법 은 2 급 작용 역 에서 1 급 작용 역 으로 3 급 작용 역 을 가 진 함수 인용 을 되 돌려 주 는 것 이다.이 인용 이 관건 입 니 다. 이 인용 이 존재 하기 때문에 관련 된 세 번 째 역할 영역 과 두 번 째 역할 영역 은 모두 이 인용 이 실 행 된 문맥 이 되 어 쓰레기 회수 체 제 는 이 체인 에서 차지 하 는 자원 을 회수 하지 못 하 게 합 니 다.이 인용 이 없 으 면 일반 함수 와 마찬가지 로 함수 가 실행 되면 자원 이 회수 된다.
        그렇다면 문제 가 생 겼 다. 도대체 폐쇄 란 무엇 인가?패 킷 을 닫 는 것 은 함수 에 포 함 된 함 수 를 말 합 니까? 아니면 1 급 으로 인 용 된 포 함 된 함 수 를 말 합 니까?아니면 다?아니면 패키지 가 끼 워 넣 는 함수 가 아니 라 끼 워 넣 는 함수 가 1 급 역할 영역 에 인용 되 었 을 때 형 성 된 메커니즘 입 니까?
function a(){  
   var i=0;   
  function b(){   
     alert(++i);   
    }   
   return b;   
 }   
 var c = a();   
 c();

이상 의 코드 를 설명 하 십시오.        a 가 실행 되 고 돌아 온 후에 패 키 지 를 닫 으 면 자바 script 의 쓰레기 회수 체 제 는 a 가 사용 하 는 자원 을 회수 하지 않 습 니 다. a 의 내부 함수 b 의 실행 은 a 의 변수 에 의존 해 야 하기 때 문 입 니 다.패 킷 의 존재 로 인해 함수 a 가 돌아 온 후에 a 중의 i 는 항상 존재 합 니 다. 이렇게 매번 c () 를 실행 할 때마다 i 는 1 을 추가 한 후에 alert 에서 i 의 값 을 냅 니 다.        그러면 a 가 함수 b 를 되 돌려 주지 않 으 면 상황 이 완전히 달라 집 니 다.a 가 실 행 된 후에 b 는 a 의 외부 로 돌아 가지 않 고 a 에 의 해 인용 되 었 을 뿐 이 고 이때 a 도 b 에 의 해 인용 되 었 기 때문에 함수 a 와 b 는 서로 인용 되 지만 외부 에 의 해 방 해 받 지 않 고 함수 a 와 b 는 GC 에 의 해 회수 된다.
자 바스 크 립 트 고급 프로 그래 밍 의 이 코드 를 보십시오.
function createFunctions(){
  var result = new Array();
  for (var i=0; i < 10; i++){
    result[i] = function(){
      return i;
    };
  }
  return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
  console.log(funcs[i]());
}

우 리 는 모두 0 ~ 9 를 출력 할 것 이 라 고 생각 했 지만 실제로는 10 개 를 출력 할 것 이다.왜 일 까요?지금 위의 코드 를 설명 하고 전체 코드 를 번역 해 보 세 요. 사실은 아래 의 과정 입 니 다.
var result = new Array();
result[0] = function(){ return i; }; //     ,      ,       i  !
result[1] = function(){ return i; }; //     ,      ,       i  !
...
result[9] = function(){ return i; }; //     ,      ,       i  !
i = 10;
funcs = result;
result = null; 
console.log(i); // funcs[0]()     return i   ,    10
console.log(i); // funcs[1]()     return i   ,    10
...
console.log(i); // funcs[9]()     return i   ,    10

알 겠 느 냐, 함수 대 () 가 실행 함수 다!단순 한 var f = function () {alert ('Hi');};창문 을 튕 기지 않 습 니 다. 뒤에 f () 를 연결 합 니 다.함수 내부 코드 를 실행 할 수 있 습 니 다.그래서 10 개 를 출력 하고 해결 방법 은 폐쇄 를 이용 하 는 것 이다.
function createFunctions(){
  var result = new Array();
  for (var i=0; i < 10; i++){
    result[i] = function(num){
        return function () {
            return num;
        }
    }(i);
  }
  return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
    console.log(funcs[i]());
}

이렇게 많은 말 을 했 는데 폐쇄 가 도대체 무엇 인지 다음 에 정리 하 겠 습 니 다. 폐쇄 는 하나의 개념 입 니 다. 함수 가 실행 되 고 메모리 가 방출 된 후에 도 메모리 가 남아 있 는 현상 을 묘 사 했 습 니 다. 이 핵심 개념 을 파악 하면 폐쇄 는 이해 하기 어렵 지 않 습 니 다.사실상 폐쇄 연장 변수의 생명주기 다.일반적인 함수 의 역할 영역 즉 변 수 는 함수 실행 이 끝 난 후에 소각 되 지만 함수 가 닫 힌 가방 을 되 돌려 주면 닫 힌 가방 이 풀 리 지 않 으 면 모든 역할 영역 체인 이 메모 리 를 차지 합 니 다.
2. 폐쇄 적 인 용도
패 킷 특징: 1. 하 나 는 함수 내부 의 변 수 를 읽 을 수 있 고 다른 하 나 는 이러한 변수의 값 을 메모리 에 계속 유지 하 는 것 입 니 다. 즉, 변수의 생명 주 기 를 연장 하 는 것 입 니 다.(외부 함수 가 실 행 된 후 내부 함수 의 실행 은 외부 환경 에서 의 변수 에 의존 하기 때문에 쓰레기 회수 체 제 는 외부 함수 의 메모 리 를 회수 하지 않 습 니 다) 패 킷 을 닫 으 면 함수 중의 변 수 를 메모리 에 저장 하고 메모리 소모 가 많 기 때문에 패 킷 을 남용 해 서 는 안 됩 니 다. 그렇지 않 으 면 웹 페이지 의 성능 문제 가 발생 하여 IE 에서 메모리 가 유출 될 수 있 습 니 다.해결 방법 은 함 수 를 종료 하기 전에 사용 하지 않 는 부분 변 수 를 모두 삭제 하 는 것 입 니 다.용도: 1. 패 키 지 를 사용 하면 JavaScript 에서 블록 급 역할 도 메 인 2 를 모방 할 수 있 고 대상 에서 개인 변 수 를 만 드 는 데 도 사용 할 수 있 습 니 다.패 킷 을 닫 아 특권 방법 (구조 함수 모드, 원형 모드, 모듈 모드, 강 화 된 모듈 모드) 을 실현 할 수 있 습 니 다.
(1) 블록 급 역할 영역 모방
블록 급 역할 영역 (사유 역할 영역 이 라 고도 함) 에 사용 되 는 익명 함수 의 문법 은 다음 과 같 습 니 다.
(function () { //         })();

이상 코드 는 익명 함 수 를 정의 하고 즉시 호출 하 였 습 니 다.함수 설명 을 괄호 에 포함 시 키 면 실제 함수 표현 식 임 을 표시 합 니 다. 그러나 아래 코드 는 오류 가 발생 할 수 있 습 니 다.
function () {
//        
}();

* * 이 유 는: * * JavaScript 는 function 키 워드 를 함수 성명 의 시작 으로 하고 함수 성명 뒤에 괄호 를 붙 일 수 없 기 때 문 입 니 다.그러나 함수 표현 식 뒤에 괄호 를 붙 일 수 있 습 니 다. 함수 성명 을 함수 표현 식 으로 바 꾸 려 면 위의 첫 번 째 코드 처럼 괄호 를 넣 으 면 됩 니 다.
어느 곳 에서 든 임시 적 으로 변 수 를 필요 로 하면 개인 역할 영역 을 사용 할 수 있 습 니 다. 예 를 들 어:
function outputNumbers (count) {
    (function () {
        for (var i = 0;i < count; i++){
            alert(i);
        }
    })();
    alert(i);//      
}

위의 코드 에 for 순환 밖 에 개인 역할 영역 이 포함 되 어 있 습 니 다.따라서 익명 함수 에서 정 의 된 모든 변 수 는 실행 이 끝 날 때 삭 제 됩 니 다.따라서 i 는 사유 작용 역 에서 만 사용 할 수 있 고 사용 후 폐기 된다.개인 역할 영역 에서 변수 count 에 접근 할 수 있 는 이 유 는 이 익명 함수 가 폐쇄 적 이 고 외부 함수 에 접근 할 수 있 는 변수 이기 때 문 입 니 다.
사유 작용 역 은 전역 작용 역 에서 함수 외부 에 자주 사용 되 기 때문에 전역 작용 역 에 너무 많은 변수 와 함 수 를 추가 하 는 것 을 제한한다.
(2) 개인 변수
함수 내부 에서 정 의 된 모든 변 수 는 개인 변수 라 고 볼 수 있 습 니 다. 함수 외부 에서 이 변 수 를 방문 할 수 없 기 때 문 입 니 다.개인 변수 와 개인 함수 에 접근 할 수 있 는 공유 방법 이 특권 방법 이 됩 니 다.
특권 방법 을 만 드 는 두 가지 방식: 1) 구조 함수 에서 특권 방법 을 정의 합 니 다.
function MyObject() { 
    //         
    var privateVariable = 10;
    function privateFunction () { 
        return false;
    }
    //    ,        ,                      
    this.publicMethod = function (){
        privateVariable++;
        return privateFunction ();
    }
}

2) 정적 사유 변 수 는 사유 역할 영역 에서 사유 변수 나 함 수 를 정의 하고 특권 방법 을 만 들 수 있 습 니 다. 기본 모델 은 다음 과 같 습 니 다.
(function () { 
    //         
    var privateVariable = 10;
    function privateFunction () { 
        return false;
    }
    //    ,                       ,              。
    MyObject = function () { 
    };
    //    
    MyObject.prototype.publicMethod = function () { 
        privateVariable ++;
        return privateFunction ();
    }

})

좋은 웹페이지 즐겨찾기