자바스크립트의 클로저(Closure) 코드를 그림과 텍스트로 심도있고 간단하게 소개합니다.

黄舟
풀어 주다: 2017-03-03 15:37:16
원래의
1121명이 탐색했습니다.

클로저 (클로저)는 Javascript를 초보자부터 심화까지 익히는 데 있어 매우 중요한 문턱입니다. 이는 Javascript 언어의 어려움이자 많은 고급 응용 프로그램의 특징이기도 합니다. 모두 폐쇄에 달려 있습니다. 아래에 나의 공부노트를 적어보세요~

시리즈 목차

  • 자바스크립트의 클로저(Closure)에 대한 심층설명

  • 자바스크립트 심층 설명

  • 자바스크립트의 프로토타입 체인과 상속에 대한 심층 소개


클로저 - 모든 곳에서


프론트 엔드 프로그래밍에서 클로저를 사용하는 경우는 의도적이든 무의식적이든, 직접적이든 간접적이든 매우 일반적입니다. 클로저는 데이터 전송을 보다 유연하게 만들 수 있습니다(예: 일부 클릭 이벤트 처리)

!function() {      
  var localData = "localData here";    
     document.addEventListener('click',    //处理点击事件时用到了外部局部变量,比如这里的localData       
        function(){              
           console.log(localData); 
    }); 
}();
로그인 후 복사

또 다른 예는 다음과 같습니다. (매우 친숙하지 않나요~~)

!function() {      
  var localData = "localData here";      
  var url = "http://www.baidu.com/";      
  $.ajax({ 
     url : url,          
     success : function() {              
        // do sth...              
        console.log(localData); 
        } 
    }); 
}();
로그인 후 복사

다른 예를 살펴보겠습니다. ~~이것은 우리가 일반적으로 클로저라고 부르는 상황입니다.

function outer() {   
  var localVal = 30;    
  return function(){      
    return localVal;    
  } 
} 
var func = outer();  
func(); // 30
로그인 후 복사

이 예에서 외부()를 호출하면 익명 함수 function()이 반환됩니다. 이 익명 함수에서는 외부()의 로컬 변수 localVal에 액세스할 수 있습니다. .outer()가 호출된 후 func()가 다시 호출되면 external()의 로컬 변수 localVal에 계속 액세스할 수 있습니다.

클로저의 개념

일반적인 함수와는 다릅니다. 함수가 직접적인 어휘 범위 외부에서 호출되는 경우에도 여전히 비지역 변수에 액세스할 수 있습니다. – 위키피디아

클로저는 다른 함수의 내부 변수를 읽을 수 있는 함수입니다. – Ruan Yifeng

Javascript 언어에서는 함수 내부의 하위 함수만 지역 변수를 읽을 수 있으므로 클로저는 간단히 "함수 내부에 정의된 함수"로 이해하면 됩니다.

그래서 클로저란 본질적으로 함수 내부와 함수 외부를 연결하는 다리입니다.

클로저의 목적

이 부분은 이 블로그에서 재현했습니다. post

클로저는 다양한 곳에서 사용될 수 있습니다. 가장 큰 용도는 두 가지입니다. 하나는 앞서 언급한 것처럼 함수 내부의 변수를 읽는 것이고, 다른 하나는 이러한 변수의 값을 메모리에 유지하는 것입니다.

function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000
로그인 후 복사

이 코드에서 결과는 실제로 클로저 f2 함수입니다. 두 번 실행했는데, 처음에는 값이 999였고, 두 번째에는 값이 1000이었습니다. 이는 함수 f1의 지역 변수 n이 항상 메모리에 저장되며 f1이 호출된 후에 자동으로 지워지지 않음을 증명합니다.

왜 이런 일이 일어나는 걸까요? 그 이유는 f1이 f2의 상위 함수이고 f2가 전역 변수에 할당되어 f2가 항상 메모리에 있고 f2의 존재가 f1에 따라 달라지므로 f1은 항상 메모리에 있고 삭제되지 않기 때문입니다. 호출이 완료된 후 가비지 수집 메커니즘(가비지 수집)에 의해 재활용됩니다.

이 코드에서 주목할 만한 또 다른 점은 "nAdd=function(){n+=1}" 행입니다. 우선 var 키워드는 nAdd 이전에 사용되지 않으므로 nAdd는 오히려 전역 변수입니다. 지역변수보다 둘째, nAdd의 값은 익명 함수이고 익명 함수 자체도 클로저이므로 nAdd는 함수 외부에서 함수 내부의 지역 변수에 대해 연산을 수행할 수 있는 setter와 동일합니다.


클로저 캡슐화


(function() {   
   var _userId = 23492;   
   var _typeId = 'item';    
   var export = {}; 

   function converter(userId) {          
     return +userId; 
   } 
    export.getUserId = function() {         
       return converter(_userId);     
   } 
   export.getTypeId = function() {          
      return _typeId; 
   }         
   window.export = export;   //通过此方式输出
}());

  export.getUserId(); // 23492 
  export.getTypeId();  // item 
  export._userId;    // undefined  
  export._typeId;    // undefined       
  export.converter; // undefined
로그인 후 복사

클로저의 특성을 사용하면 복잡한 함수 논리를 캡슐화할 수 있습니다. 예를 들어, 내보내기 시 메소드(getUserId, getTypeId)를 호출하여 함수의 전용 변수에 간접적으로 액세스하지만, _userId는 내보내기._userId를 직접 호출하여 얻을 수 없습니다. 이것도 Node에서 자주 사용하는 기능이에요~


흔히 저지르는 실수: 루프 폐쇄


다음과 같은 경우에는, 3p를 더하면 값은 aaa, bbb, ccc입니다. 우리가 원하는 것은 aaa를 클릭하여 1을 출력하고, bbb를 클릭하여 2를 출력하고, ccc를 클릭하여 3을 출력하는 것입니다.

document.body.innerHTML = "<p id=p1>aaa</p>" + "<p id=p2>bbb</p><p id=p3>ccc</p>";  
for (var i = 1; i < 4; i++) {      
  document.getElementById(&#39;p&#39; + i).         
    addEventListener(&#39;click&#39;, function() {         
    alert(i); // all are 4! 
    });  
}
로그인 후 복사

결과 aaa, bbb, ccc 클릭하면 모두 알림(4)~~

문제는 초기화가 완료되었을 때 i 값이 이미 4라는 점입니다

원하는 것을 얻으려면 aaa를 클릭하여 1을 출력하고, bbb를 클릭하여 2를 출력하고, ccc를 클릭하여 3을 출력합니다. 각 루프에서 익명 함수로 래핑해야 합니다. 다음과 같이 즉시 실행됩니다. 이렇게 하면 클로저 환경의 i에서 매번 Alert(i)의 값을 가져오고 이 i는 각 루프의 할당 i에서 가져오고 1, 2, 3을 출력합니다.

document.body.innerHTML = "<p id=p1>aaa</p>" + "<p id=p2>bbb</p>" + "<p id=p3>ccc</p>";  
for (var i = 1; i < 4; i++) {
  !function(i){ //②再用这个参数i,到getElementById()中引用     
    document.getElementById(&#39;p&#39; + i).       
      addEventListener(&#39;click&#39;, function() {         
      alert(i); // 1,2,3
     });  
  }(i);  //①把遍历的1,2,3的值传到匿名函数里面
}
로그인 후 복사

생각하는 질문

다음 두 코드의 결과를 이해할 수 있다면 클로저의 작동 메커니즘을 이해해야 합니다. (루안 선생님의 답변) 이 질문은 초 단위로 요약되어 있습니다~~

Code Fragment 1

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());
로그인 후 복사

Code Fragment 2

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()());
로그인 후 복사

위는 JavaScript 클로저에 대한 자세한 설명입니다. (마감) 코드 사진과 텍스트가 자세히 소개되어 있으니 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!

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