난 노력 자바 스크립트 폐쇄 주위에 내 머리를 정리하고 내 어려운합니다.
내부 함수를 반환하면 직계 부모에 정의 된 모든 변수에 액세스 할 수 있습니다.
이것이 어디에서 유용할까요? 어쩌면 나는 아직 내 머리를 가지고 있지 않았을 것입니다. 온라인에서 본 대부분의 예제는 실제 코드를 제공하지 않고 모호한 예제를 제공합니다.
누군가 나에게 클로저의 실제 사용을 보여줄 수 있습니까?
예를 들어 이것입니까?
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>
답변
당신이주는 예는 훌륭한 것입니다. 클로저는 우려를 매우 명확하게 분리 할 수있는 추상화 메커니즘입니다. 예는 의미론 (오류보고 API)에서 계측 (계산 호출)을 분리하는 경우입니다. 다른 용도는 다음과 같습니다.
-
매개 변수화 된 동작을 알고리즘에 전달 (클래식 고차 프로그래밍) :
function proximity_sort(arr, midpoint) { arr.sort(function(a, b) { a -= midpoint; b -= midpoint; return a*a - b*b; }); }
-
객체 지향 프로그래밍 시뮬레이션 :
function counter() { var a = 0; return { inc: function() { ++a; }, dec: function() { --a; }, get: function() { return a; }, reset: function() { a = 0; } } }
-
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
객체하지만 그것은 스크립트의 사용자가 볼 것 그들이 원한다면 그들은 심지어 심지어 소스 코드를 필요로하지 않고, 그것을 변경할 수 있습니다. 그러나 날짜 조회 기능을 반환하는 익명 함수로 묶여 있기 때문에 조회 기능을 통해서만 액세스 할 수 있으므로 이제 변조 방지됩니다.