Javascript – scope 이야기 클로저(Closure) – 한 번 더 정리 2/2
지난번에 알아본 클로저 개념을 다시 상기시키면서 아래 예제를 살펴보자.
클로저 함수는 외부 함수의 실행이 끝나더라도 외부 함수 내 변수를 사용할 수 있다.
클로저는 이처럼 특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게하는 폐쇄성을 갖는다.아래는 서핑하다가 클로저의 잘못된 이해로 실수를 범하기 쉬운 사례 샘플이라하여,이해를 돕고자 그대로 가져왔다.
for(var i=0; i<5;i++) // 외부함수
{
console.log(i); // 0 ,1, 2 ,3 ,4
myArray[ i ] = function() { return i } // 내부함수
}
// 위에 코드를 예상해보면,
// myArray[0] = function() { return 0};
// myArray[1] = function() { return 1};
// myArray[2] = function() { return 2};
// myArray[3] = function() { return 3};
// myArray[4] = function() { return 4};
for(var i in myArray)
{
console.log(myArray[i]());
}
// 출력을 예상해 본다면,
// console.log(myArray[0]); // 예상출력 0 – 실제 출력 5
// console.log(myArray[1]); // 예상출력 1 – 실제 출력 5
// console.log(myArray[2]); // 예상출력 2 – 실제 출력 5
// console.log(myArray[3]); // 에상출력 3 – 실제 출력 5
// console.log(myArray[4]); // 예상출력 4 – 실제 출력 5
잘못 이해하고 있는 관점에서보면 myArray [0~4] = function() { return 5 }; 를 한
느낌이 들것이다.
왜 이런결과가 나올까 이유를 알고나면 01,2,3,4, 출력을 예상한것이 이상하다는것을 알게 될것이다.
지난번 시간에 이야기 했듯이 실제로 함수(변수)가 사용하는 시점에서,
그 변수를 바라보고 있는 변수 참조에 대한 이야기를 했었다.
for(var i=0; i<5;i++)
{
console.log(i); // 0 ,1, 2 ,3 ,4
myArray[ i ] = function() { return i }
}
외부함수 for 에서 선언된, i 변수를 , 내부 함수 myArray[ i ] = function() { return i } 에서 사용이 되는데, 여기서는 { return i } 를 말한다.
위의 for 의 지역변수 i 는 for 문을 벗어나려면 i < 5 조건을 만족해야하는데,
반복하여 증가하면서 i 가 5 가되어서야 루프를 탈출하게 된다.
// 출력 for 문
for(var i=0; i<5;i++)
{
console.log( myArray[x]() ) ;
}
출력 for 문에서 myArray[x]() 함수를 호출 하면서, 위에 지역변수 i 를 “참조” 하게 되는데
for 문을 벗나오면서 i 가 마지막으로 가지고 있는 값은 “5” 가 되어 그 참조된 주소에서
계속 5를 가져오는 상황이 일어 나는것이다.
좀 더 이해를 쉽게하기 위해 , 코드를 수정해보자
if ( i == 2) i = 100; // 0, 1 , 2 일때 i 를 100 으로 셋팅하여 루프를 탈출해보자
// 다시 위에 코드를 예상해보자 어떻게 보이는지
// myArray[0] = function() { return i }; // 참조되는 i 현재 0
// myArray[1] = function() { return i }; // 참조되는 i 현재 1
// myArray[2] = function() { return i }; // 참조되는 i 현재 2 , i = 100 셋팅 탈출
// myArray[3] = “”;
// myArray[4] = “”;
for(var a in myArray)
{
console.log(myArray[a]());
}
그럼 출력은?
위의 소스를 다시한번 살펴보자,
변수의 레퍼런스(참조)개념으로 살펴보면 아래와 같다.
if ( i == 2) i = 100;
i = 0 일때 ( 변수 i를 참조하는 느낌 . 값 참조가 아님 X)
myArray[0] = function() { return 0 };
i = 1 일때 (변수 i를 참조하는 느낌. 값 참조가 아님 X)
myArray[0] = function() { return 1 };
myArray[1] = function() { return 1 };
i = 2 일때 ( 변수 i를 참조하는 느낌. 값 참조가 아님 X)
myArray[0] = function() { return 2 };
myArray[1] = function() { return 2};
myArray[2] = function() { return 2};
if (i == 2) i = 100;
for 문의 i < 5 조건을 탈출하는 순간은 i == 2 일때 i 가 100 이 되고, 다음처리때 탈출하
게된다. 그럼 for 문을 탈출했을때 myArray 함수의 i 값은 다음과 같이 i 를 참조하고 있다.
myArray[0] = function() { return 101 };
myArray[1] = function() { return 101};
myArray[2] = function() { return 101};
그래서 결과는,
101 // index 0
101 // index 1
101 // index 2
(100 아니고 101 인 이유는 i++ 를 먼저 실행하고 i < 5 조건을 비교하기때문)
을 3 번 출력하게된다. (for ~ in [3] , [4] 번째 배열은 undefined 되어서 제외되었다.)