강의 출처 : The Complete JavaScript Course 2022 Jonas (Udemy)
자주 쓰이는 것은 아님. function을 scope으로 감싸기 보다는 block scope 이용가능하므로.
const runOnce = function () {
console.log('This will never run again');
};
runOnce(); //This will never run again
//IIFE
(function () {
console.log('This will never run again');
})(); //This will never run again
(() => console.log('This will never run again'))(); //This will never run again
We don't make closure manually
Closure happens automatically in a certain situation
const secureBooking = function () {
let passengerCount = 0;
return function () {
passengerCount++;
console.log(`${passengerCount} passengers`);
};
};
const booker = secureBooking();
booker(); //1 passengers
booker(); //2 passengers
booker(); //3 passengers
Call Stack 내에서
- Global EC - secureBooking = < f >
- secureBooking() EC - passengerCount = 0
- Global EC - booker < f > 추가
- secureBooking() EC callstack 내에서 사라짐. 임무를 수행했으므로. (함수 return하면 사라짐.)
주목해야할 점 : secureBooking() EC is gone but booker function is still available somehow.
booker()을 코드 내에 적음으로서 callstack 내에 booker()EC 실행된다!
어떻게 booker()이 passengeCount에 access 하는 것인가? closure 덕분
중요) Any function always has access to the variable environment of the execution context in which the function was created even after that execution context is gone.
중요) Closure : VE(variable environment) attached to the function, exactly as it was at the time and place the function was created
Therefore booker function will get access to secureBooking's variable envionment which contains the passengerCount variable. 이런 connection 을 closure 이라고 부르는 것!
좀 더 간단히 말하면 closure을 통해 함수는 자신이 생성될 때의 환경(Lexical environment)을 기억한다.
closure 덕분에 함수가 계속해서 함수가 만들어졌던 곳의 variable에 접근할 수 있는 것.
A closure basically has priority over the scope chain.
A closure is the closed-over variable environment of the execution context in which a function was created, even after that execution context is gone.
A closure gives a function access to all the variables of its parent function, even after that parent function has returned. The function keeps a reference to its outer scope, which preserves the scope chain throughout time.
즉 function이 reference를 outer scope에 저장하고 있기 때문에, 스콥체인을 저장하고 있는 것 => 그러므로 그들의 parents function의 변수들에 접근이 가능한 것!! (애초에 parents function에 접근할 수 있도록 만드는 것이 scope chaining이므로! )
A closure makes sure that a function doesn't loose connection to variable that existed at the function's birth place.
A closure is like a backpack that a function carries around wherever it goes. This backpack has all the variables that were present in the environment where the function was created.
We do NOT have to manually create closures, this is a JavaScript feature that happens automatically. We can't even access closed-over variables explicitly. A closure is NOT a tangible JavaScript object. Because closure is just an internal property of a function. closure이 발생하는 것을 우리가 관찰할 수는 있으나 variable에 직접 접근할 수 는 없음!
참고) [[]] => 우리가 직접 접근할 수 없는 정보!
Example 1
let f;
const g = function () {
const a = 23;
f = function () {
console.log(a * 2);
};
};
const h = function () {
const b = 777;
f = function () {
console.log(b * 2);
};
};
g();
f(); //46 // closure 일어남 => g() EC가 끝났음에도 변수 a 에 접근이 가능하다.
// Re-assigning f function
h();
f(); //1554
Example 2
const boardPassengers = function (n, wait) {
const perGroup = n / 3;
setTimeout(function () {
console.log(`We are now boarding all ${n}passengers`);
console.log(`There are 3 groups, each with ${perGroup} passengers`);
}, wait * 1000);
console.log(`Will start boarding in ${wait}seconds`);
};
const perGroup = 1000;
boardPassengers(180, 3);
setTimeout 함수는 boardPassengers와 별개로 실행이 되지만 여전히 boardPassengers의 변수들에 접근이 가능하다 => closure is created
global variable인 perGroup이 아닌 boardPassengers 내에 있는 perGroup을 사용함. => callback 함수가 boardPassenger함수의 variable environment를 close over할 것이기 때문. Closure even has a priority over the scope chain.