[javascript] JavaScript에서 클로저를 실제로 사용하는 것은 무엇입니까?

노력 자바 스크립트 폐쇄 주위에 내 머리를 정리하고 내 어려운합니다.

내부 함수를 반환하면 직계 부모에 정의 된 모든 변수에 액세스 할 수 있습니다.

이것이 어디에서 유용할까요? 어쩌면 나는 아직 내 머리를 가지고 있지 않았을 것입니다. 온라인에서 본 대부분의 예제는 실제 코드를 제공하지 않고 모호한 예제를 제공합니다.

누군가 나에게 클로저의 실제 사용을 보여줄 수 있습니까?

예를 들어 이것입니까?

var warnUser = function (msg) {
    var calledCount = 0;
    return function() {
       calledCount++;
       alert(msg + '\nYou have been warned ' + calledCount + ' times.');
    };
};

var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();



답변

클로저를 사용하여 다음과 같은 작업을 수행했습니다.

a = (function () {
    var privatefunction = function () {
        alert('hello');
    }

    return {
        publicfunction : function () {
            privatefunction();
        }
    }
})();

보시다시피 a이제 클로저 내부에만 존재하는를 호출 하는 메소드 publicfunction( a.publicfunction())가 있는 객체 privatefunction가 있습니다. 당신은 할 수 없습니다 호출 privatefunction(예 : 직접 a.privatefunction()단지) publicfunction().

최소한의 예이지만 용도가 보입니까? 우리는 이것을 공개 / 비공개 방법을 시행하기 위해 사용했습니다.


답변

사용자 가 웹 페이지 에서 버튼클릭 한 횟수계산 한다고 가정합니다 .
이를 위해 onclick버튼의 이벤트에서 변수의 개수를 업데이트 하는 함수를 트리거 합니다.

<button onclick="updateClickCount()">click me</button>  

이제 다음과 같은 많은 접근 방식이있을 수 있습니다.

1) 전역 변수카운터 를 늘리는 함수를 사용할 수 있습니다 .

var counter = 0;

function updateClickCount() {
    ++counter;
    // do something with counter
}

그러나 함정은 페이지의 모든 스크립트updateClickCount() 가을 호출하지 않고 카운터를 변경할 수 있다는 것 입니다.


2) 이제 함수 내부에서 변수를 선언하려고 생각할 수 있습니다.

function updateClickCount() {
    var counter = 0;
    ++counter;
    // do something with counter
}

그러나 이봐! updateClickCount()기능이 호출 될 때마다 카운터는 다시 1로 설정됩니다.


3) 중첩 함수 에 대한 생각 ?

중첩 함수는 “위”범위에 액세스 할 수 있습니다.
이 예에서 내부 함수 updateClickCount()는 상위 함수의 카운터 변수에 액세스 할 수 있습니다.countWrapper()

function countWrapper() {
    var counter = 0;
    function updateClickCount() {
    ++counter;
    // do something with counter
    }
    updateClickCount();
    return counter;
}

updateClickCount()외부 에서 함수에 도달 할 수 있고 counter = 0매번 한 번만 실행할 수있는 방법을 찾아야 한다면 카운터 딜레마를 해결할 수 있습니다 .


4) 구조 폐쇄! (자기 호출 기능) :

 var updateClickCount=(function(){
    var counter=0;

    return function(){
     ++counter;
     // do something with counter
    }
})();

자체 호출 기능은 한 번만 실행됩니다. counter를 0으로 설정하고 함수 표현식을 리턴합니다.

이런 식 updateClickCount으로 기능이됩니다. “멋진”부분은 부모 범위의 카운터에 액세스 할 수 있다는 것입니다.

이것을 JavaScript 클로저 라고합니다 . 함수가 ” private “변수 를 가질 수 있습니다 .

counter익명 함수의 범위에 의해 보호되며, 단지 추가 기능을 사용하여 변경할 수 있습니다!

클로저에 대한보다 생생한 예 :

<script>
        var updateClickCount=(function(){
    	var counter=0;

    	return function(){
    	++counter;
    	 document.getElementById("spnCount").innerHTML=counter;
    	}
      })();
    </script>

    <html>
	 <button onclick="updateClickCount()">click me</button>
	  <div> you've clicked
		<span id="spnCount"> 0 </span> times!
	 </div>
    </html>


참조 : https://www.w3schools.com/js/js_function_closures.asp


답변

당신이주는 예는 훌륭한 것입니다. 클로저는 우려를 매우 명확하게 분리 할 수있는 추상화 메커니즘입니다. 예는 의미론 (오류보고 API)에서 계측 (계산 호출)을 분리하는 경우입니다. 다른 용도는 다음과 같습니다.

  1. 매개 변수화 된 동작을 알고리즘에 전달 (클래식 고차 프로그래밍) :

    function proximity_sort(arr, midpoint) {
        arr.sort(function(a, b) { a -= midpoint; b -= midpoint; return a*a - b*b; });
    }
  2. 객체 지향 프로그래밍 시뮬레이션 :

    function counter() {
        var a = 0;
        return {
            inc: function() { ++a; },
            dec: function() { --a; },
            get: function() { return a; },
            reset: function() { a = 0; }
        }
    }
  3. jQuery의 이벤트 처리 및 AJAX API와 같은 이국적인 흐름 제어를 구현합니다.


답변

나는이 질문에 대답하는 데 늦었지만 2018 년에도 여전히 답을 찾는 사람에게 도움이 될 수 있습니다.

자바 스크립트 클로저를 사용 하여 애플리케이션에서 스로틀디 바운스 기능 을 구현할 수 있습니다 .

조절 :

제한은 시간이 지남에 따라 함수를 호출 할 수있는 최대 횟수로 제한합니다. “이 기능은 100 밀리 초마다 최대 한 번 실행”과 같이

코드 :

const throttle = (func, limit) => {
  let isThrottling
  return function() {
    const args = arguments
    const context = this
    if (!isThrottling) {
      func.apply(context, args)
      isThrottling = true
      setTimeout(() => isThrottling = false, limit)
    }
  }
}

수신 거부 :

Debouncing은 함수가 호출되지 않고 일정 시간이 지날 때까지 함수에 제한을 두지 않습니다. “이 함수를 호출하지 않고 100 밀리 초가 지난 경우에만 실행”과 같이

암호:

const debounce = (func, delay) => {
  let debouncing
  return function() {
    const context = this
    const args = arguments
    clearTimeout(debouncing)
    debouncing = setTimeout(() => func.apply(context, args), delay)
  }
}

보시다시피 모든 웹 앱은 부드러운 UI 경험 기능을 제공해야하는 두 가지 아름다운 기능을 구현하는 데 도움이되었습니다.

누군가에게 도움이되기를 바랍니다.


답변

예, 이것이 유용한 폐쇄의 좋은 예입니다. warnUser에 대한 호출 calledCount은 해당 범위에 변수를 작성하고 변수에 저장된 익명 함수를 리턴 warnForTamper합니다. calledCount 변수를 사용하는 클로저가 여전히 있기 때문에 함수가 종료 될 때 삭제되지 않으므로,에 대한 각 호출 warnForTamper()은 범위가 지정된 변수를 증가시키고 값을 경고합니다.

StackOverflow에서 가장 일반적인 문제는 누군가가 각 루프에서 증가하는 변수의 사용을 “지연”하려는 경우이지만 변수의 범위가 지정되므로 변수에 대한 각 참조는 루프가 끝난 후 발생합니다. 변수의 종료 상태 :

for (var i = 0; i < someVar.length; i++)
    window.setTimeout(function () {
        alert("Value of i was "+i+" when this timer was set" )
    }, 10000);

이로 인해 모든 경고 i는 루프가 종료 될 때 증가한 값 과 동일한 값을 표시합니다 . 해결책은 변수에 대한 별도의 범위 인 새 클로저를 만드는 것입니다. 이는 즉시 실행되는 익명 함수를 사용하여 수행 할 수 있습니다.이 함수는 변수를 수신하고 상태를 인수로 저장합니다.

for (var i = 0; i < someVar.length; i++)
    (function (i) {
        window.setTimeout(function () {
            alert("Value of i was "+i+" when this timer was set" )
        }, 10000);
    })(i); 


답변

특히 JavaScript (또는 모든 ECMAScript) 언어에서 클로저는 인터페이스를 표시하면서 기능 구현을 숨기는 데 유용합니다.

예를 들어, 날짜 클래스 유틸리티 메소드를 작성 중이고 사용자가 색인으로 요일 이름을 검색 할 수 있지만 사용자가 후드 아래에서 사용하는 이름 배열을 수정하지 못하게한다고 가정하십시오.

var dateUtil = {
  weekdayShort: (function() {
    var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    return function(x) {
      if ((x != parseInt(x)) || (x < 1) || (x > 7)) {
        throw new Error("invalid weekday number");
      }
      return days[x - 1];
    };
  }())
};

점을 유의 days배열은 단순히의 속성으로 저장 될 수있는 dateUtil객체하지만 그것은 스크립트의 사용자가 볼 것 그들이 원한다면 그들은 심지어 심지어 소스 코드를 필요로하지 않고, 그것을 변경할 수 있습니다. 그러나 날짜 조회 기능을 반환하는 익명 함수로 묶여 있기 때문에 조회 기능을 통해서만 액세스 할 수 있으므로 이제 변조 방지됩니다.


답변

모질라 개발자 네트워크실용 폐쇄 섹션이 있습니다 .