티스토리 뷰

IT/Javascript

Javascript - 클로저(closure)

Normal_One 2017. 3. 26. 11:22

 클로저(closure)는 javascript에서 닫혀진 내부 함수가 바깥에 선언되어 있는 변수들에 접근할 수 있는 함수들을 의미합니다. 글로는 잘 이해가 되지 않을텐데 먼저 아래 예제를 보겠습니다.


1
2
3
4
5
6
7
8
9
10
<script type="text/javascript">
function init() {
   var name = "name";
   function displayName() {//클로저
     alert(name);//name 변수 출력
   }
   displayName();
 }
init();
</script>
cs


 위 코드를 실행시키면 브라우저가 켜지면서 'name'이라는 단어와 함께 팝업창을 실행하는 것을 볼 수 있습니다. 여기서 함수 displayName()은 함수 init() 내부에 있는 함수인데, 자신의 영역에 name이라는 변수가 있지 않음에도 name 변수를 불러와서 출력하는 것을 확인할 수 있습니다. 
 일반적으로 java에서 method를 선언하면 전역변수 외에는 자기 내부에서 선언한 변수가 아닌 이상 불러 올 수 없는 것이 일반적인데, javascript는 자신의 영억(scope) 외에서 선언 된 변수를 건들일 수 있는 것입니다. 

클로저를 활용하여 java의 private 속성 사용하기

클로저는 javascript의 고수가 되기 위해 필요한 개념이라고 많은 사람들이 얘기하고 있습니다. 이 중에서도 가장 클로저를 잘 활용할 수 있는 방법은 바로 private 속성을 사용할 수 있다는 것입니다. java에서는 기본적으로 private 속성을 제공하고 있으나 javascript에서는 제공하고 있지 않습니다. 하지만, 이 클로저 개념을 잘 활용하면 java의 private 속성을 사용할 수 있습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script type="text/javascript">
    function novel(title) { 
        return {  
            get : function(){//제목을 보여주는 클로저   
            return title;  },  
            set : function(_title) {//제목을 변경하는 클로저   
            title = _title;  } 
            }
    };
    var novel1 = novel("노인과 바다");
    var novel2 = novel("데미안");
    alert(novel1.get());
    alert(novel2.get());
    novel1.set("개미");
    alert(novel1.get());
    alert(novel2.get());
</script>
cs


 본 코딩을 실행해보면 차례대로 팝업 창에 "노인과 바다", "데미안", "개미", "데미안"이 출력되는 것을 확인할 수 있습니다. java의 getter와 setter를 활용한 것과 마찬가지입니다. 이를 잘 활용하면 private 속성 외에도 여러 가지 확장이 가능할 것으로 보입니다. 아래 계산기 예제는 위와 동일하게 설계하여 계산기의 기능을 수행하도록 되어있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script type="text/javascript">
    function calculator(num) { 
        return {plus : function(_num){//더하기 기능을 하는 클로저   
                return num = num + _num;  },  
                minus : function(_num){//빼기 기능을 하는 클로저   
                return num = num - _num;  },  
                multiple : function(_num){//곱하기 기능을 하는 클로저   
                return num = num * _num;  },  
                division : function(_num){//나누기 기능을 하는 클로저   
                return num = num / _num;  } 
                }
            }
 
    var cal = new calculator(10);
    alert(cal.plus(10));
    alert(cal.plus(10));
    alert(cal.minus(10));
    alert(cal.multiple(10));
    alert(cal.minus(10));
    alert(cal.division(10));
</script>
cs


클로저 활용 시 반복문에서의 주의사항

 클로저는 좋은 기능을 제공하지만 반복문에서 사용시 때때로 문제를 일으킵니다. 일단 아래 예제를 보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
<script type="text/javascript">
    var arr = [];
    for (var i = 0; i < 5; i++) { 
        arr[i] = function(){  
                    return i; }
                }
 
    for (var index in arr) { 
        console.log(arr[index]());
    }
</script>
cs
 
 
 위 예제는 생활코딩에서 가져온 예제인데, 저희가 콘솔창에 결과 값으로 기대하는 값은 0,1,2,3,4 이지만 실제 콘솔창에 입력되는 값들은 5,5,5,5,5입니다. 이게 5가 계속 실행되는 이유는 arr[i]의 값에 함수 자체가 저장되기 때문입니다. 우리는 for문이 돌면서 0,1,2,3,4인 변수들을 저장하길 바라며 코딩을 했지만 결과적으로는 함수가 저장되고 그러므로 콘솔을 통해서 찍었을 때, 위 i가 for에서 수행한 연산 식이 끝난 후의 값인 5가 다섯 번 보이는 것입니다. 따라서 이를 올바르게 고친 예제는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript">
        var arr = [];     
        for (var i = 0; i < 5; i++) {         
            arr[i] = function(id) {             
                            id = i;             
                            return id}(i); //함수 선언 후 i 값을 넣어 바로 실행함}; 
 
        for ( var index in arr) {         
            console.log(arr[index]);     
        }
 
</script>
cs


 위 예제에 대해 설명하자면, function(id)라는 함수를 선언하고 그 안에서 id라는 변수가 i 값을 받게 설정한 후에 바로 이 함수에 i를 넣어 실행시킨 모습입니다.  

현재 들어서는 jquery나 다양한 플러그인들이 제공되기에 더 쉽고 강력하게 다양한 기능들을 사용할 수 있어서 클로저가 그렇게 중요한 개념은 아니라고 생각합니다. 다만, 알아두면 나중에 프레임워크의 코어 부분을 설계할 때나 여타 다른 언어에서 클로저가 나올 때 잘 활용될 수 있을거라 생각합니다. 
 

참고사이트:


댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday