함수를 어디에 정의했는지에 따라 상위 스코프를 결정하는 정적 스코프를 의미한다.
생명 주기가 종료된 외부 함수의 변수를 참조하는 중첩 함수를 클로저라고 한다.
함수가 일급 객체이며, 렉시컬 스코프를 따르기 때문이다.
React의 useState는 setState를 통해서만 상태를 변경할 수 있다. useState 수명 주기가 끝난 후에 setState로 상태에 접근하고 변경할 수 있으므로 클로저를 기반으로 구현되어 있을 것이라고 짐작할 수 있다.
function useState(initialValue) {
let state = initialValue;
const getState = () => state;
const setState = (newValue) => {
state = newValue;
};
return [getState, setState];
}
컴포넌트가 렌더링된 후 실행되는 useEffect의 클린업 함수는 함수가 정의됐을 당시에 상태 값을 참조한다. 이를 통해 클린업 함수가 클로저임을 알 수 있다.
setTimeout의 콜백 함수 혹은 이벤트 핸들러가 외부 데이터를 사용할 때 유용하다.
function outerFunction() {
let message = 'Hello, world!';
setTimeout(function innerFunction() {
console.log(message);
}, 1000);
}
outerFunction();
함수에 일부 인자를 미리 전달하여 함수를 반환하는 경우에 사용할 수 있다.
const debounce = function(func, wait) {
let timeoutId = null;
return function (event) {
const self = this;
clearTimeout(timeoutId);
timeoutId = setTimeout(func.bind(self, event), wait);
};
}
const moveHandler = function(e) {
console.log('move event 처리');
};
document.body.addEventListener('mousemove', debounce(moveHandler, 500));
const wrap = (fn) => {
return function() {
const res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
history.pushState = function() {
const res = history.pushState.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
};
history.replaceState = function() {
const res = history.pushState.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
};