# 클로저 란?
나는 프론트엔드 개발을 하면서,
클로저란 단어을 전혀 모르고 있었다.
개발을 하면서 사용은 해봤지만, 이게 클로저 였단 것을 몰랐다.
그럼 이제부터 알아보자
클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다. 클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용된다. - 생활코딩(클로저) 참고
개념만 보았을때 이해를 했다면, 정말 그 사람은 이해력이 참 좋은 것이다.
하지만 나는 그런 사람이 아니란 것을 알기 때문에, 좀더 자세히 알아보자.
# 클로저 예시
1 2 3 4 5 6 7 8 9 | function outter(){ // 외부 함수 function inner(){ // 내부 함수 var title = 'coding everybody'; console.log(title); } inner(); } outter(); // 외부 함수 호출 // 출력 : coding everybody | cs |
1 2 3 4 5 6 7 8 9 | function outter(){ // 외부 함수 var title = 'coding everybody'; function inner(){ // 내부 함수 console.log(title); } inner(); } outter(); // 외부 함수 호출 // 출력 : coding everybody | cs |
가장 기본적인 예시이다.
클로저는 외부함수 안에 내부함수를 선언하여,
외부함수에서만 사용할 수 있는 외부함수를 만들고,
외부함수가 종료 되어도 내부함수에서는 외부함수를 접근할 수 있도록 해준다.
아마 이것만 보고는 이걸 왜 사용하는지 모를것이다.
아래 예제를 참고해 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var Closer = { TodayMeal : function(meal){ // 외부 함수 return { GetTodayMeal : function(){ // 내부 함수 1 return meal; // 외부 함수에 존재하는 meal을 리턴해 준다. }, SetTodayMeal : function(SetMeal){ // 내부 함수 2 meal = SetMeal; // 외부 함수에 존재하는 meal의 값을 변경해 준다. }, } } } const Meal = Closer.TodayMeal("쌀밥"); // 클로저를 Meal이란 변수에 넣어준다. Meal.GetTodayMeal(); // Meal을 가져온다 // 출력 : 쌀밥 Meal.SetTodayMeal("콩밥"); // "콩밥"이란 값을 셋팅해준다. Meal.GetTodayMeal(); // Meal을 가져온다 // 출력 : 콩밥 | cs |
주석과 같이 읽어보면 어느정도 이해는 갈 것이다.
클로저 함수를 사용함으로써 변수를 직접 접근하지 않고
간접적으로 접근이 가능할 수 있도록 한다.
이로써 meal이란 외부함수 변수는 오직 내부함수에서만 접근이 가능한 것이다.
이로써 협업을 하면서 직접적으로 수정되지 말아야할 변수를 은닉화 시키는대에 도움을 준다.
# 클로저를 사용하면서 생길수 있는 착각
클로저를 사용하면서 "이게 맞겠지?" 하면서 짜다가,
"어?! 이게 왜 안되지?" 하는 부분이 존재할 수 있다.
아래 예제를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /*이 예제는 생활코딩에서 참고하였습니다.*/ var arr = [] // 배열 선언 for(var i = 0; i < 5; i++){ arr[i] = function(){ // 각 배열마다 i 값을 리턴해 주는 무명 함수를 넣어준다. return i; // 이로써 0, 1, 2, 3, 4가 출력되는 것을 기대한다. } } for(var index in arr) { console.log(arr[index]()); // 각 배열에 함수를 호출한다. } // 출력 : 5 // 출력 : 5 // 출력 : 5 // 출력 : 5 // 출력 : 5 | cs |
위 예제는 흔히하는 실수중 하나이다.
각 배열에 i값이 0, 1, 2, 3, 4 가 리턴되어지도록 세팅해 놓고
그 값을 기대하지만, 출력되는 결과는 5가 5번 나오게된다.
왜 그럴까?
먼저 for문에서의 var i는 정의되어진 내부 함수의 외부 변수가 아닌,
그저 for문이란 스코프 안에 Function-Scope일 뿐이기 때문이다.
즉 클로저가 아니란 말이다.
그렇기 때문에 i가 증가되어질수록 Function-Scope의 특성상,
모든 배열의 i값이 같이 증가하게 된다.
(사실 ES6부터 let과 const가 나와서 var 대신 Block-Scope인 let을 쓰면 정상적으로 입력되어진다.)
(단, const는 안된다. const는 상수의 역활을 하기 때문에
참조형을 제외한 값으로 변경하면 안된다.)
그럼 어떻게 해야할까?
아래 예제를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /*이 예제는 생활코딩에서 참고하였습니다.*/ var arr = [] // 배열 선언 for(var i = 0; i < 5; i++){ arr[i] = function(id){ // 각 배열마다 id란 매게변수를 가지고 있는 외부 함수를 넣어준다. return function(){ // 내부 함수를 선언해 외부함수에 id값을 리턴해준다. return id; } }(i); // 각 배열에 클로저를 넣기 전 바로 호출을 해준다. } for(var index in arr) { console.log(arr[index]()); // 각 배열에 함수를 호출한다. } // 출력 : 0 // 출력 : 1 // 출력 : 2 // 출력 : 3 // 출력 : 4 | cs |
# 마무리
위 포스트는 제가 직접 제작한 것 입니다.
그렇기 때문에 틀린점이나 설명이 엉성한 점이 존재할 수 있습니다.
만약 틀린점이나 설명이 엉성한 부분이 존재하면 댓글로 알려주세요.
빠른 처리 하도록 하겠습니다.
티스토리 앱으로는 댓글 이용이 불가능 하므로 웹 브라우저로 봐 주세요
(URL : http://junprogramer.tistory.com/)
읽어주셔서 감사합니다.
'잡다한 기술' 카테고리의 다른 글
[백준 알고리즘 2839]설탕 배달 (0) | 2018.07.01 |
---|---|
[JAVA SCRIPT/자바 스크립트]호이스팅(Hoisting)를 알아보자 (0) | 2018.06.25 |
우아한 형제들 2차 코딩테스트 탈락 (0) | 2018.06.24 |
[K-Move/해외인턴/IT인턴]미국에서 받은 주차 티켓 처리하기 (0) | 2018.06.19 |
[알고리즘]팰린드롬(palindrome) 체크 알고리즘 (0) | 2018.06.18 |