번역하면 "폐쇄"
상위 스코프의 변수를 가르키는 함수이며, 클로저가 만들어진 환경을 기억함
왜 다 5가 나오는가?
var는 함수 스코프를 따른다.
i는 전역 스코프에 등록됌.
setTimeout은 비동기단으로 이동
그 중에 for문이 계속 돌아가기때문에 i가 0,1,2,3,4,5가 됌.
싱글쓰레드기 때문에 setTimeout이 다 끝나더라도 큐에 남음
for가 다 끝난 후 setTimeout이 실행되고, 함수안에 i가 없으므로 상위로 이동.
i는 5기 때문에 모두 5가 나오는 것임
클로저가 가장 유용하게 쓰이는 상황 중 하나는 현재 상태를 기억하고 있다가 상태가 변경되면 그것을 최신상태로 유지하는 것이다.
<!DOCTYPE html>
<html>
<body>
<button class="toggle">toggle button</button>
<div class="txt">
<h1>toggle test</h1>
</div>
<script>
let txtField = document.querySelector('.txt');
let toggleBtn = document.querySelector('.toggle');
let toggle = (function () {
let isVisable = false;
// 1.클로저를 반환
return function () {
txtField .style.display = isVisable ? 'block' : 'none';
// 3. 상태 변경
isVisable = !isVisable;
};
})();
// 2. 이벤트 프로퍼티에 클로저를 할당
toggleBtn.onclick = toggle;
</script>
</body>
</html>
위의 예제는 간단하게 toggle 버튼을 통해 텍스트가 보였다가 안보였다가하는 예제인데,
결과는 아래처럼 나온다.
위의 코드에서 보면
1.즉시 실행함수가 있는데 이는 함수를 반환한 뒤 바로 소멸된다. 이때 반환된 힘수는 자신이 생성됐을때의 Lexical 환경에 속한 변수인 isVisable을 기억하는 클로저가 된다. 클로저가 기억하는 변수인 isVisable은 txt 표시 상태를 나타낸다.
2.클로저를 버튼 이벤트 프로퍼티에 할당을 했다. 이제 이 클로저를 제거하지 않는한 isVisable 은 소멸되지 않는다.
3. 버튼 클릭시 클로저가 호출되게되는데 이때 txt요소의 표시 상태를 나타내는 변수인 isVisable 값이 변경이 되게 된다. 이 변수는 클로저에 의해 참조 되고 있기 때문에 변경된 최신 값을 계속 유지할 수가 있다.
보통 프로그래밍 초보자들은 전역변수를 통해서 공유될 변수를 작성하는데, 이렇게하면 오류가 발생할 확률이 매우 높아지게 된다. 그 이유는 누구든 이 전역변수에 접근할 수 있기 때문에 의도치 않게 값이 변경될 여지가 많다. 이는 심각한 장애로 이어질 수도 있다.
클로저를 이용하면 이러한 문제를 단번에 해결할 수가 있다.
<!DOCTYPE html>
<html>
<body>
<button id="plus">+</button>
<p id="count">0</p>
<script>
let plusBtn = document.getElementById('plus');
let countTxt = document.getElementById('count');
let plus= (function () {
// 카운트 상태를 유지하기 위한 자유 변수
let count = 0;
// 클로저를 반환
return function () {
return count++;
};
}());
plusBtn.onclick = function () {
countTxt .innerHTML = plus();
};
</script>
</body>
</html>
위의 예시는 숫자를 하나씩 카운트하는 코드인데, 여기서 count라는 변수가 만약 전역변수로 선언되어서 카운팅되게 만들어졌다면 이는 굉장히 위험한 프로그램이 될 것이다.
그런데 위처럼 클로저를 이용해 내부로 철저히 숨김으로써 데이터를 은닉화 시켰다.
객체지향 언어에서 private키워드를 이용해 캡슐화 시키는 것처럼 javascript에서도 클로저의 특징을 이용해 비슷한 기능을 구현할 수 있는 것이다.