-
Modern JavaScript 클로저FrontEnd/JavaScript 2023. 1. 29. 13:26
1. 클로저란
- excution context 에서 필요한 개념으로, 함수 선언시 렉시컬 환경 (어디에 함수를 선언하였는가, 외부/내부)의 조합을 의미
- excution context 관점에서 innerFunc이 호출되면 context에 stack이 쌓이고 Variable Object와 Scope chain, this에 바인딩할 객체가 결정된다.
- outerFunc의 Activation Object, 함수자신을 순차적으로 바인딩하며 scope chain이 바인딩한 객체가 렉시컬 스코프 범주의 개념이다.
- 반환된 내부 함수가 자신이 선언되었을 때의 환경 (Lexical environment)인 스코프를 기억하여 자신이 선언되었을 때의 환경(스코프)밖에서 호출되어도 Lexical environment를 기억하는 함수 -> 스코프체인을 통해 참조
- 상태 변경이나 가변데이터를 피하고 불변성을 지향하는 함수형 프로그래밍으로 부수효과를 최대한 억제하여 오류를 피함 (안정성)
- 메모리 차원에서는 손해보는 환경
function outerFunc() { var x = 10; var innerFunc = function () { console.log(x); }; innerFunc(); } outerFunc(); // 10
* innerFunc 함수가 변수x 검색 --> 실패 --> outerFunc (활성객체) 에서 변수 x (자유변수) 검색 --> 성공 --> 반환 (콜스택, 실행 컨택스트에서 outerFunc 소멸)
- 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되어도 외부함수의 지역 변수에 접근할 수 있다.
2. 클로저 활용
- 상태유지 : 현상태를 기억하고 변경된 상태 유지
- isShow (Lexical environment의 변수, 생성시 기억) : 클로저가 기억하는 변수
- 이벤트 핸들러인 클로저를 제거하지 않는한 isShow는 소멸하지 않는다. (현상태 기억)
- 버튼 클릭시 이벤트핸들러 클로저 호출
- isShow값 변경 및 최신상태 유지
<!DOCTYPE html> <html> <body> <button class="toggle">toggle</button> <div class="box" style="width: 100px; height: 100px; background: red;"></div> <script> var box = document.querySelector('.box'); var toggleBtn = document.querySelector('.toggle'); var toggle = (function () { var isShow = false; // ① 클로저를 반환 return function () { box.style.display = isShow ? 'block' : 'none'; // ③ 상태 변경 isShow = !isShow; }; })(); // ② 이벤트 프로퍼티에 클로저를 할당 toggleBtn.onclick = toggle; </script> </body> </html>
- 전역 변수 사용 억제
- counter (전역변수) : 전역변수로 언제든 접근 및 변경 가능
- increase (클로저) : 의도치 않게 값이 변경 되는 것을 방지 (자신이 생성됐을 때의 환경을 기억)
<!DOCTYPE html> <html> <body> <p>전역 변수를 사용한 Counting</p> <button id="inclease">+</button> <p id="count">0</p> <script> var incleaseBtn = document.getElementById('inclease'); var count = document.getElementById('count'); // 카운트 상태를 유지하기 위한 전역 변수 var counter = 0; function increase() { return ++counter; } incleaseBtn.onclick = function () { count.innerHTML = increase(); }; </script> </body> </html>
- 정보의 은닉
- public property : counter가 this에 바인딩된 프로퍼티라면 Counter는 외부에서 접근 가능
- private 하게 사용 : 아래 예시는 Counter 내에서 선언된 변수 counter는 외부에서 접근 불가
function Counter() { // 카운트를 유지하기 위한 자유 변수 var counter = 0; // 클로저 this.increase = function () { return ++counter; }; // 클로저 this.decrease = function () { return --counter; }; } const counter = new Counter(); console.log(counter.increase()); // 1 console.log(counter.decrease()); // 0
'FrontEnd > JavaScript' 카테고리의 다른 글
Modern JavaScript Built-in Object (0) 2023.02.11 Modern JavaScript Object-Oriented Programming (0) 2023.02.11 Modern JavaScript 함수 호출방식 (0) 2023.01.28 Modern JavaScript Strict mode (1) 2023.01.28 Modern JavaScript 스코프 (0) 2023.01.22