secureBooking
함수는 로컬 스코프의 passengerCount
변수를 업데이트하는 함수를 리턴한다.booker
는 secureBooking
함수의 리턴값으로 passengerCount
변수를 업데이트하는 함수를 받는다.booker
실행하면 결과가 어떻게 될까.passengerCount
변수가 업데이트되고 console.log
가 실행된다.
이미 실행이 끝난
secureBooking
의 함수 내에 선언된passengerCount
변수를 전역 스코프의booker
함수가 사용할 수 있었던 이유가 무엇일까.
booker
함수는 전역 스코프에 존재하는 함수이다.
secureBooking
함수는 실행이 끝났기 때문에 execution context의 변수 환경도 완전히 사라졌다.
하지만 booker
함수는 당시 존재했던 passengerCount
변수에 계속 접근할 수 있다.
booker
함수는 전역 스코프이기 때문에 scope chain으로도 passengerCount
변수에는 접근할 수 없다.
이를 가능하게 한 것은 바로 closure이다.
booker
에 할당된 함수는 call stack에서 사라진 secureBooking
함수의 execution context에서 선언되었다.booker
함수는 자신이 선언된 함수의 execution context가 사라져도 그 execution context의 변수 환경에 항상 접근할 수 있다.booker
함수는 closure를 이용하여 자신이 선언된 곳인 secureBooking
함수의 변수 환경에 항상 접근할 수 있다.다시 정리하면, 함수는 함수 자신의 변수 환경과 자신이 선언된 함수의 변수 환경에 접근할 수 있고 이러한 연결고리를 closure라 한다.
하지만 콘솔을 통해 함수 내부의 closure 속성을 직접 볼 수 있다.
[[]]
로 표시된 것은 내부 속성이기 때문에 코드로 접근할 수 없다는 의미이다.closure는 자신이 선언된 부모 함수의 변수 환경에 항상 접근할 수 있다고 하는데, 부모 함수의 부모 함수, 즉 조부모 함수의 변수 환경에는 어떤 방식으로 접근될까
결과는 다음과 같다
i
와 부모 함수에서 선언된 변수 j
에 정상적으로 접근할 수 있었다.let f;
const g = () => {
const a = 4;
f = function() {
console.log(a*5)
}
}
const h = () => {
const b = 7;
f = function() {
console.log(b*2);
}
}
g(); // 함수 할당
f(); // 20
h(); // 함수 재할당
f(); // 14
const boardPassengers = (n, wait) => {
const perGroup = n / 3;
setTimeOut(() => {
console.log(`We are now boarding all ${n} passengers`);
console.log(`There are 3 groups. each with ${perGroup}
}, wait * 1000);
};
boardPassengers(180, 3);
(function() {
const header = document.querySelector('h1');
header.style.color = 'red';
// 콜백함수는 여전히 header 변수에 접근할 수 있다.
document.body.addEventListener('click', () => {
header.style.color = 'blue';
})
})()
https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures
https://poiemaweb.com/js-closure
https://www.udemy.com/course/the-complete-javascript-course/