바닥코딩
클로저 본문
클로저?
자바스크립트에는 자바스크립트 만의 고유의 개념은 아니지만 '클로저' 라는 것이 존재합니다. 정의를 살펴보면
“A closure is the combination of a function and the lexical environment within which that function was declared.”
- 클로저는 함수와 그 함수가 선언됐을 떄의 렉시컬 환경과의 조합이다 -
이런 의마라고 한다는데 ... 사실 이해가 되지 않았습니다. 그래서 클로저를 사용한 여러 예제를 찾아보고 실제 사용되는 의미를 파악해본 결과 일반적으로 클로저는 어떤 함수가 자신의 스코프가 아닌 외부에서 선언된 변수에 접근 하는것을 의미한다라는 정의를 내릴 수 있었습니다. 사실 이말도 이해가 안될거라고 생각합니다... 제일 빠른 이해를 위해서 예제로 바로 넘어가겠습니다
클로저 사용 예제
간단한 예제로 위 그림과 같은 버튼을 하나 만들고 버튼을 클릭하였을때 카운트가 증가하는 함수를 구현해본다고 생각해봅시다.
<!DOCTYPE html>
<html>
<body>
<button id="increase">+</button>
<p id="count">0</p>
<script>
var IBtn = document.getElementById("increase");
var count = document.getElementById("count");
function increase(){ count 1증가
count = 0;
count++;
return count;
}
IBtn.onclick = function () { // 카운트 변수를 화면에 출력
count.innerHTML = increase();
};
</script>
</body>
</html>
위와 같이 코드를 작성하였을 경우 결과는 어떻게 될까요?
위 코드에서는 버튼을 아무리 여러번 누른다 해도 1이상 증가하지 않습니다. 다들 아시다시피 함수가 호출이 되면서 count를 다시 0으로 초기화 하는 부분이 존재하기 때문입니다.
이 문제를 해결하기 위해선 코드를 아마 이렇게 작성 해야 할 것입니다.
<!DOCTYPE html>
<html>
<body>
<button id="increase">+</button>
<p id="count">0</p>
<script>
var IBtn = document.getElementById("increase");
var count = document.getElementById("count");
var countNum = 0; //전역 변수 선언
function increase(){
countNum ++; // 전역변수 증가
return countNum;
}
IBtn.onclick = function () { //클로저가 현재 상태를 기억하는지 확인
count.innerHTML = increase();
};
</script>
</body>
</html>
위 코드에서는 countNum 이라는 전역변수를 선언해 전역변수를 증가하여 반환하도록 수정을 했습니다 결과는 아래와 같이 클릭 때 마다 1씩 증가가 정확되 되는 것을 확인 할 수 있습니다.
위 코드에서는 아무 문제가 발생하지 않습니다. 그렇지만 만약 저 countNum 이라는 전역변수가 변경될 수 있는 상황이 발생한다면 어떨까요? 클릭을 할때마다 0 1 2 3 4 5 6 이렇게 증가를 해야하는 상황에서 한번이라도 countNum 이 0으로 초기화 되는 상황이 발생한다면 위 상황에서 결과는 0 1 2 3 4 (4번 클릭후 초기화) 0 1 2 3 4 5 6 이런식으로 내가 생각했던 방향과는 다른 상황이 발생 할 수 있습니다.
잠시 이 얘기는 미루어두고 아래 코드를 보겠습니다
<!DOCTYPE html>
<html>
<body>
<button id="increase">+</button>
<p id="count">0</p>
<script>
var IBtn = document.getElementById("increase");
var count = document.getElementById("count");
var increase = function(){
var count = 0; // 카운트 변수
/*클로저를 반환*/
return function(){
return count++;
}
}();
IBtn.onclick = function () { //클로저가 현재 상태를 기억하는지 확인
count.innerHTML = increase();
};
</script>
</body>
</html>
위 코드의 increase 라는 변수에 할당 한 함수 안에서 count를 선언하고 count를 1증가한 값을 반환하는 함수를 반환합니다(function을 반환) 위코드를 보면 사실 처음에 봤던 코드와 크게 다를 것이 없어 보입니다, 위코드도 아까와 같이 count 가 0으로 초기화 때문에 버튼을 아무리 눌러도 1만 출력하는 모습을 예상할 수 있습니다. 하지만 위코드는 아무 문제 없이 0 1 2 3 4 5 6 ... 우리가 원하는 결과를 출력합니다.
이것이 클로저의 역할입니다 위 코드는 즉시실행함수를 통해 increase를 즉시 실행해 호출되고 소멸됩니다 하지만 자바스크립트의 렉시컬 환경은 이를 기억하고 있습니다. 즉 자바스크립트는 자신이 선언되었을 때의 함수의 지역변수를 기억합니다
이러한 코드를 작성하였을 경우 함수는 생성과 동시에 소멸 되지만 자신이 속해있던 지역변수의 값을 기억하기 때문에 의도 치 않은 변경이 발생하더라도 지역변수의 값은 바뀌지 않습니다(참조 함수가 없어질 경우만 소멸) 즉 일정 함수 안에 속해있는 내부함수가 외부함수가 소멸하더라도 외부함수 스코프 내용을 기억하는 이러한 매커니즘을 클로저라고 할 수 있습니다
'JavaScript > vanilla js' 카테고리의 다른 글
Arrow function (0) | 2021.03.17 |
---|---|
프로토 타입 (0) | 2021.03.17 |
자바스크립트 스코프(scope) (0) | 2020.07.25 |
var, let, const (0) | 2020.07.12 |
바닐라 JS란 무엇인가 (2) | 2020.06.06 |