JavaScript Closure 클로저

Develop My Life·2020년 4월 15일
0

JavaScript

목록 보기
8/15

Closure란?

내부함수가 외부함수의 맥락에 접근할 수 있는 것

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
<script type="text/javascript">
	function outter(){
		var outter_var = "code"; //외부함수에 정의되어 있는 지역 변수
		return function(){
			alert(outter_var);
		}
	}
	inner = outter(); //외부함수 outter가 호출되고 리턴 값으로 내부 함수가 호출되고 내부함수가 외부함수의 지역변수를 사용하고 종료된다.
	inner(); //출력값 code
	//내부함수를 호출하지만 이미 종료된 외부함수의 변수를 사용할 수 있다.
</script>
</body>
</html>

내부함수란?

함수 안에 있는 함수

Closure를 사용하는 이유

함수 안에서만 사용되는 함수를 안쪽에 함수를 선언하여 코드의 응집성을 높인다.

Closure의 특징

내부함수에서 외부함수에서 선언된 변수에 접근할 수 있다.
이미 실행이 종료된 외부함수에 있는 변수에 접근할 수 있다.
외부함수의 매개변수를 private variable이라고 한다.

Closure의 기능

  1. 내부함수로만 외부함수의 변수에 접근할 수 있다.
  2. 특정 메소드만이 접근할 수 있는 변수를 private variable이라고 한다.
  3. 변수를 아무나 수정할 수 없게하여 소프트웨어가 망가질 가능성을 줄인다.

Closure 예시

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
<script type="text/javascript">
	function circle(radius){ //외부함수의 변수를 매개변수의 형태로 radius로 선언한다.
		return{
			get_radius : function(){
				return radius; //내부함수에서 외부함수의 변수 radius를 리턴한다.
			},
			set_radius : function(new_radius){
				radius = new_radius; //내부함수에서 외부함수의 변수 radius를 new_radius로 바꾼다.
			} 
		}
	}
	first_circle = circle('4'); //외부함수의 radius를 4로 선언한다.
	second_circle = circle('6'); //외부함수의 radius를 6으로 선언한다.
	alert(first_circle.get_radius()); //출력값 4
	alert(second_circle.get_radius()); //출력값 6
	first_circle.set_radius('8'); //first_circle의 radius를 8로 바꾼다.
	second_circle = circle('10'); //second_circle의 radius를 10으로 바꾼다. // 의문점!
	alert(first_circle.get_radius()); //출력값 8
	alert(second_circle.get_radius()); //출력값 10
	//radius는 get_radius나 set_radius를 통해서만 접근 가능한 아주 private한 변수이다.
</script>
</body>
</html>

Closure 사용 시 흔한 실수(with for)

Closure 사용 시 흔한 실수 예시

JavaScript에서는 for문이나 if문 안의 변수는 전역변수로 취급되기 때문에 for문 안의 함수는 내부함수라고 할 수 없다.

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
<script type="text/javascript">
	var arr = [];
	for(var i = 0; i < 5; i++){
		arr[i] = function(){ 
			return i;
		}
	}
	for(var index in arr){
		document.write(arr[index]()); //출력 55555
		//외부함수의 변수 i로 내부함수의 리턴 값을 지정해주어 01234의 출력값을 예상 했을 수 있지만 for문의 변수 i는 외부함수의 변수가 아니라 전역함수이다.
	}
</script>
</body>
</html>

Closure 사용 실수 개선 예시

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
<script type="text/javascript">
	var arr = [];
	for(var i = 0; i < 5; i++){//for에 있는 변수 i 는 지역변수가 아니라 전역변수이기때문에 외부함수의 변수 개념이 아니다.
		arr[i] = function(id){//외부함수의 지역변수를 id로 선언
			return function(){
				return id; // 내부함수의 리턴값을 외부함수의 변수 id로 한다.
			}
		}(i); //외부함수를 바로 실행함으로써 내부함수를 실행시키고 arr배열에 i 값을 넣어준다.
	}
	for(var index in arr){
		document.write(arr[index]()); //출력 01234
	}
</script>
</body>
</html>

Closure 의문점

Closure를 사용하는 목적이 외부함수에 있는 매개변수를 private variable이라고 하여 아무나 쉽게 접근할 수 없게 하는 것이라고 이해했다. 하지만 Closure의 예시의 코드를 보면 first_circle = circle('4');로, second_circle = circle('6');으로 radius를 초기화 해주었고 그 후에 first_circle의 radius를 8로 set_radius라는 내부함수 메소드를 이용하여 radius에 접근하여 변경해주었고 second_circle의 radius를 10으로 다시 초기화와 같은 형태로 radius에 접근하여 변경해주었다.
이 때 다시 초기화해주는 방법으로 radius에 재접근할 수 있었는데 이 경우가 있는데 외부함수의 매개변수에 접근하는 방식으로 Closure를 굳이 써야하는 건가에 대해 의문이 들었다. 앞으로 공부해가면서 의문점을 이해해봐야겠다.

0개의 댓글