클로저 이해하기
클로저의 기본적인 예
<script>
// 클로저의 기본적인 예
function sum(base) {
var inClosure = base;
return function(adder) {
return inClosure + adder;
};
};
var fiveAdder = sum(5); // 5 and return function
console.log(fiveAdder.toString());
fiveAdder(3); // inClsure(5) + adder(3) = 8
var threeAdder = sum(3); // 3 and return function
console.log(threeAdder.toString());
</script>
위 소스에서도 함수 안에 다른 함수를 선언하고 외부에서 내부 함수를 사용하는 클로저의 특징을 확인할 수 있다.
외부에서 sum()함수를 호출하면 파라미터 base를 통해 넘어온 값은 inClosure변수에 저장된다. 그리고 내부 함수에서 inClosure변수를 참조한다.
var fiveAdder = sum(5);
선언되는 부분부터 보면, var fiveAdder를 통해 sum()함수가 호출되고 sum()함수의 파라미터인 base는 5로 넘어와서 inClsure변수도 5로 설정된다. 그리고 inClosure변수를 참조하는 내부 함수를 반환하여 fiveAdder에 저장한다.
이제부터 fiveAdder를 통해 함수를 호출하게 되면 스코프 체인을 따르게 된다.
그리고 나중에 fiveAdder를 통해 함수를 호출하게 되면 fiverAdder가 레퍼런스를 가지고 스코프 체인을 사용하게 되는 것이다.
fiveAdder(3);
이제 fiveAdder(3)이 호출되면, 위에 스코프 체인에서 inClosure는 5를 갖고, 내부함수의 파라미터 adder로 들어온 값에 3을 더하여 8이라는 값이 계산된다.
var threeAdder = sum(3);
다음으로 threeAdder를 호출하면 새로운 스코프 체인을 생성한다.
이처럼 같은 함수를 통해 받은 값은 각각의 함수가 생성되어, fiveAdder, threeAdder로 호출하는 스코프 체인이 만들어진다.
이처럼 클로저를 통해 각 함수는 자기만의 고유한 값을 보유하고 스코프 체인을 유지하면서 그 체인 안에 있는 모든 변수의 값들을 유지한다.
한가지 추가해보면, fiveAdder와 threeAdder변수의 형태는 아래처럼 서로 같다.
하지만 형태 이외에, fiveAdder !== threeAdder로 두개의 변수는 같지 않다. sum()함수를 호출할 때마다 같은 모양의 함수들이 새롭게 나오지만, 두 함수가 할당받은 스코프 체인, 숨겨져 있는 클로저가 다르기 때문이다.
다음은 setInterval()함수를 통한 클로저의 발생이다.
<button id="btnToggle">Toggle</button>
<div id="divPending">Pending</div>
<script>
// setInterval() 함수를 통한 클로저 발생
(function() {
var pendingInterval = false,
div = document.getElementById("divPending"),
btn = document.getElementById("btnToggle");
function startPending() {
if(div.innerHTML.length > 13) {
div.innerHTML = "Pending";
}
div.innerHTML += ".";
};
btn.addEventListener("click", function() {
if(!pendingInterval) {
pendingInterval = setInterval(startPending, 500);
} else {
clearInterval(pendingInterval);
pendingInterval = false;
}
});
}());
</script>
위 소스를 실행하면 아래와 같은 화면이 나온다. Toggle버튼을 클릭하면 “Pending”뒤에 “.”을 하나씩 추가하다가 일정 개수가 넘으면 다시 초기화하는 방식으로 동작한다.
var pendingInterval = false,
div = document.getElementById("divPending"),
btn = document.getElementById("btnToggle");
위 변수들은 내부에서만 접근 할 수 있도록 private변수로 선언했다. 그리고 startPending()함수 안에 있을 법한 divPending을 가져오는 부분을 상위 스코프에 미리 가져다 놓음으로써, 매번 <div>를 getElementById로 탐색해서 가져오지 않도록 했다.
아래는 클로저가 발생한 부분들이다.
if(div.innerHTML.length > 13) {
div.innerHTML = "Pending";
}
if문에서 상위 스코프 div변수를 참조하는 부분과
pendingInterval = setInterval(startPending, 500);
setInterval()함수에서 첫번째 인자로 startPending함수를 사용하는 부분이다.
이런 경우를 보면, 함수 안에 함수가 있어서 내부에 있는 함수가 반환되지 않고 이벤트 콜백함수로 호출될 때도 클로저가 발생하는 것을 알 수 있다.
'JavaScript | TypeScript > Javascript 시작하기' 카테고리의 다른 글
[ Javascript ] 자바스크립트의 변수 (0) | 2022.04.13 |
---|---|
[ Javascript ] 클로저의 실제 활용 예 (0) | 2022.04.12 |
[ Javascript ] 클로저란 ? (0) | 2022.04.06 |
[ Javscript ] 자바스크립트 스코프와 클로저 (0) | 2022.04.04 |
[ Javascript ] 예외처리 (0) | 2022.02.27 |