민서네집

자바스크립트 클로저(Closure) 퀴즈 본문

Javascript

자바스크립트 클로저(Closure) 퀴즈

브라이언7 2012. 2. 25. 13:09
[퀴즈 원문] http://blog.javarouka.me/2012/01/blog-post_2408.html

Quiz 4

function setter(aryUnits) {
    for(var i=0; i < aryUnits.length; i++) {
        var id = i + 1;
        aryUnits[i] = new Object();
        aryUnits[i].getId = function() {
            return id;
        }
    }
}
var ary = new Array(5);
setter(ary);
document.write(ary[3].getId());


1) 실행오류
2) undefined
3) 4
4) 5


정답) 화면에 5 가 찍힌다.
 
해설)
 
자바스크립트의 객체가 참조 타입이라는 것과 클로저의 스코프에 대해 묻는 문제입니다
빈 5만큼의 길이를 갖는 배열을 선언한 뒤 함수에 인자로 주고 있습니다.

참조 타입으로 전달되므로 함수에서 배열에 어떠한 조작을하면 리턴값이 없어도 인자의 배열은 내용물이 변합니다.

함수 안에서는 getId라는 함수를 가진 객체를 할당하고 있지만, 클로저의 스코프상 모든 배열객체들은 같은 메모리상의 id를 참조할 겁니다.

for 문이 종료되며 id 변수는 5가 할당되고, 배열의 모든 객체의 getId는 5를 반환합니다.
답은 따라서 5 가 됩니다.


여기서 질문 하나!
 
document.write(ary[3].getId());
 
했을때 4 가 출력되게 하려면? (배열 처음부터 차례로 1,2,3,4,5 숫자가 들어가게 하려면?)
 
http://blog.outsider.ne.kr/506 을 참고해서 다음과 같이 바꿔봤다. 


<html>
<script type="text/javascript">
 
function setter(aryUnits) {
    for(var i=0; i < aryUnits.length; i++) {
        var id = i + 1;
        aryUnits[i] = new Object();
        aryUnits[i].getId = function() {
            return (function(m) {
                document.write(m);
                return m;
            })(id)
        }
        aryUnits[i].getId();
    }
}
var ary = new Array(5);
setter(ary);
 
document.write(ary[3].getId());
</script>
<html>


그래도 여전히 답은 5가 출력된다.

document.write(ary[3].getId()); 를 실행할때 return 할 변수에 대한 할당이 5로 다시 되기 때문이다.
 
getId() 함수 선언부 안에서 document.write() 으로 찍어보면 알 수 있다.
 
값을 저장할 변수가 있어야 한다.
 
다음과 같이 하면 된다.

<html>
<script type="text/javascript">
 
function setter(aryUnits) {
    for(var i=0; i < aryUnits.length; i++) {
        var id = i + 1;
        aryUnits[i] = new Object();
        aryUnits[i].m = id;
        aryUnits[i].getId = function() {
            return this.m;
        }
    }
}
var ary = new Array(5);
setter(ary);
 
document.write(ary[3].getId());
 
</script>
<html>
Comments