내부함수가 외부함수의 맥락에 접근할 수 있는 것
<!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>
함수 안에 있는 함수
함수 안에서만 사용되는 함수를 안쪽에 함수를 선언하여 코드의 응집성을 높인다.
내부함수에서 외부함수에서 선언된 변수에 접근할 수 있다.
이미 실행이 종료된 외부함수에 있는 변수에 접근할 수 있다.
외부함수의 매개변수를 private variable이라고 한다.
<!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 사용 시 흔한 실수 예시
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를 사용하는 목적이 외부함수에 있는 매개변수를 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를 굳이 써야하는 건가에 대해 의문이 들었다. 앞으로 공부해가면서 의문점을 이해해봐야겠다.