First written: 23-02-15
Uploaded: 23-08-03
for(var i=0; i<10; i++){
console.log(i);
}
console.log(i); // 10
loading = false;
if(!loading){
var limit = 5;
var result = makeSomething(limit);
console.log(result);
}
console.log(limit); // 5
바라기로는 for문이나 if문 모두 block scope였으면 좋겠지만, 안타깝게도 var i=0;
, var limit = 5;
등등이 global scope
에 선언된다. 슬픈 일이다. 하지만 다행히도 ES6부터 우리에게 let
과 const
가 나타났다.
for(let i=0; i<10; i++){
console.log(i);
}
console.log(i); // Uncaught ReferenceError: i is not defined
loading = false;
if(!loading){
const limit = 5;
const result = makeSomething(limit);
console.log(result);
}
console.log(limit); // Uncaught ReferenceError: limit is not defined
이런 형식이 조금은 명시적이지 못하다는 느낌이 있다면 아래와 같이 해도 좋다.
if(!loading){
{
const limit = 5;
const result = makeSomething(limit);
console.log(result);
} // explicit block
}
명시적으로(물론 자주 볼 수 있는 코드 형태는 아니지만) scope가 표현되어 훨씬 이해하기에 좋다.
Block scope를 해주면 좋은 점 중 하나는 Garbage collection과도 관련이 있다. 아래의 코드를 보자.
function bigProcess(bigData) {
/* ... */
}
var reallyBigData = { /* ... */ };
bigProcess(reallyBigData);
var btn = document.querySelector('#btn');
btn.addEventListener('click', function clickHandler(e) {
/* ... */
}, false);
clickHandler
함수는 reallyBigData
가 필요가 없음에도 같은 scope에 있기 때문에 reallyBigData
가 memory를 잡아먹는 것을 감수해야만 한다. 하지만 코드를 아래와 같이 바꾼다면?
function bigProcess(bigData) {
/* ... */
}
{
let reallyBigData = { /* ... */ };
bigProcess(reallyBigData);
}
var btn = document.querySelector('#btn');
btn.addEventListener('click', function clickHandler(e) {
/* ... */
}, false);
이제 "Engine"
은 clickHandler
에게 reallyBigData
가 필요없다는 것을 눈치챌 것이다. bigProcess(reallyBigData)
가 실행된 뒤, 메모리를 많이 잡아먹던 reallyBigData
는 곧바로 수거될 것이다.
참고 서적 : 카일 심슨, 2017, 한빛미디어, 『YOU DON'T KNOW JS: 타입과 문법, 스코프와 클로저』