자바스크립트 스코프(scope)

스코프 문제에서 기억해야할 4가지

1. 블록 안에서 선언된 let,const로 선언된 변수는 블럭범위(중괄호{}로 감싸진범위)를 벗어날 수 없다.

2. 함수 안에서 var로 선언된 변수는 함수범위(function(){})를 벗어날 수 없다.

3. 블록이나 함수 내부에서 변수를 찾다가 없으면 상위의 블록이나 함수에서 그래도 없으면 더 상위로 계속 올라가서 찾는다. 이런 것을 ‘스코프 체인’이라 부른다.

4. 함수도 변수와 같다. 내부에서 실행될 함수를 찾다가 없으면 더 상위의 범위로 계속 찾아 올라간다.

반복문과 비동기함수가 만나면 스코프문제가 발생한다.

반복문과 비동기 함수가 만나면 함수가 의도한대로 동작하지 않는다. 왜냐하면, 비동기 함수는 동기적인 코드들보다 나중에 실행된다. 그리고 실행되는 순간에 비동기함수 내부에서 사용되는 변수나 함수를 찾는다.

예를 들면 아래와 같은 경우이다.

for(var i=0; i < 50; i++){ setTimeout(function(){ console.log(i) }, 1000) }
Code language: JavaScript (javascript)

위의 코드에서 우리가 기대하는 것은 1초마다 숫자가 0부터 49까지 찍히는 것이다.
0 1 2 3 4 …. 49 이런식으로 말이다.

하지만 결과는 50 50 50 50 50 50 50 50 50 … 50 만 50번 찍힌다.

왜냐하면, 한참뒤에 실행되는 비동기 함수 setTimeout()함수는 이미 For문의 변수 i가 반복이 모두 끝나버린 후에 실행되기 때문이다. 이미 i는 0부터 49까지 모두 돌고 마지막에 i가 50이 되는 순간에 끝나고 이때 setTimeout가 실행되기 때문에 50만 계속 찍히는 것이다.

반복문에서 비동기함수 스코프 해결방법

중간에 함수 하나를 끼워 넣고 다른 변수를 사용한다. 클로저용 함수를 끼워 넣고 바로 실행시킨다.

for(var i=0; i < 50; i++){ function closer(dd){ //여기 setTimeout(function(){ console.log(dd); }, 1000) }; closer(i); //여기 };
Code language: JavaScript (javascript)

즉시 실행함수로 해도 상관없다.

for(var i=0; i < 50; i++){ (function (dd){ //여기 setTimeout(function(){ console.log(dd); }, 1000) })(i); //여기 };
Code language: JavaScript (javascript)

위와 같이 코드를 수정하면 이제 1초마다 숫자가 0 1 2 … 49까지 콘솔에 찍힌다. 반복문과 비동기 함수가 만나면 항상 변수의 스코프 문제가 발생하지 않는지를 유념해야 한다.

답글 남기기

4 × 4 =