흔히 하는 자바스크립트 클로저와 관련된 실수

@codemaru · December 12, 2008 · 2 min read

[js]var funcs = new Array(2);

for(var i=0; i<funcs.length; ++i)
{
funcs[i] = function() { alert(i); }
}

funcs0;[/js]
간단한 자바 스크립트 코드입니다.
뭐가 출력될까요? 3이 출력됩니다.

고쳐봅시다.

[js]var funcs = new Array(2);

for(var i=0; i<funcs.length; ++i)
{
funcs[i] = function() { return function() { alert(i); } };
funcs[i] = funcsi;
}

funcs0;[/js]
의미가 좀 불명확하죠.
아래와 같이 고치면 확실히 무슨 일을 하는 코드인지 눈에 들어옵니다.

[js]var funcs = new Array(2);

function GenerateFunction(i)
{
return function() { alert(i); }
}

for(var i=0; i<funcs.length; ++i)
{
funcs[i] = GenerateFunction(i);
}

funcs0;[/js]
설명해 봅시다.
클로저에 관한 건데요. 첫 번째 샘플은 for문이 마치 클로저같은 역할을 하는 것처럼 보이지만 아닙니다. 자바스크립트 클로저는 항상 함수랑 관계가 있기 때문입니다. 즉, 저기는 클로저가 없습니다. 그러니 i가 저장된 런타임 정보는 글로벌 밖에 엄죠. 그러니 마지막 값인 3이 출력되는 겁니다.

마지막 예제를 살펴봅시다. GenerateFunction안에서 리턴되는 함수에서는 GenerateFunction 함수 안의 값인 i를 참조하고 있습니다. 즉, 클로저가 생긴거죠. 그래서 리턴된 함수가 계속 살아 있는 동안 해당 컨텍스트 정보도 파괴되지 않고 같이 살아 있습니다. 그래서 0이 출력되는 겁니다.

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중