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