closure에 대하여 araboza

frenchkebab·2021년 9월 18일
0

javascript 지식

목록 보기
11/36
post-thumbnail

다음 글은 생활코딩 - 클로저 글을 바탕으로 작성되었습니다.

closure


클로저란 무엇인가?

closure내부함수외부함수context에 접근할 수 있는 것을 가리킨다.


내부함수


내부 함수는 외부 함수의 지역변수에 접근할 수 있다.

다음의 코드를 살펴보자.
'내부함수외부함수지역변수에 접근할 수 있다'는 것이 무엇인지 와닿을 것이다.

function outter() {
  var title = 'coding everybody';
  function inner() {
    alert(title);
  }
  inner();
}
outter();

<실행 결과>

(alert) coding everybody

closure


클로저란 무엇인가?

외부함수가 실행이 끝나서 소멸된 이후에도 내부함수외부함수지역변수접근할 수 있는데, 이러한 매커니즘을 클로저라고 한다.

function outter() {
  var title = 'coding everybody';
  return function() {
    alert(title);
  }
}
inner = outter();
inner();

<실행결과>

(alert) coding everybody

inner = outter(); 에서 inner에는 outter()return 값인 이름 없는 함수가 담긴다.
그 다음 줄의 inner();로 넘어오면, outter은 이미 return을 끝마치고 함수의 실행이 끝났으므로, 이 함수의 지역변수가 소멸되는 것이 자연스럽다.

하지만 맨 마지막 줄을 실행했을 때, coding everybody가 실행된 것은,
외부함수지역변수title이 소멸되지 않았음을 의미힌다.

클로저란, 내부함수외부함수지역변수에 접근할 수 있고,
외부함수는 외부함수의 지역변수를 사용하는 내부함수소멸할 때까지 소멸하지 않는 특성을 의미한다.


조금 더 복잡한 예시

function factory_movie(title) {
    return {
        get_title : function () {
            return title;
        },
        set_title : function(_title) {
            title = _title
        }
    }
}

1.

closure를 이용하여, 영화의 제목을 저장하고 있는 객체를 정의하고 있다.
return되는 객체 안에 정의된 함수들은, factory_movie내부함수로 볼 수 있다.

매개변수 또한 지역변수이므로, 아래의 두 내부함수들에서 title의 값을 참조할 수 있다.

여기서 특이한 점은,
set_title 내의 함수에서의 title매개변수 title을 참조하고 있으므로, 이 값이 바뀌면 factory_movie매개변수 title또한 변하게 된다.

또한, get_titleset_title은 서로 외부함수인 factory_movie의 지역변수인 title을 서로 공유하게 된다.


let ghost = factory_movie('Ghost in the shell');
let matrix = factory_movie('Matrix');

위의 두 변수 ghostmatrix에는 각각 get_titleset_title이라는 메소드를 담고 있는 컨테이너인 객체가 담겨있다.


2.

console.log(ghost.get_title());
console.log(matrix.get_title());

<실행 결과>

Ghost in the shell
Matrix

ghostmatrix에는 각각 자신들이 실행될 때의 context에서의 외부함수지역변수가 유지되고 있고, 그것에 접근할 수 있다.


3.

ghost.set_title('공각기동대');
console.log(ghost.get_title());
console.log(matrix.get_title());
공각기동대
Matrix

ghost.set_title()title 값을 바꾸어도, ghost객체가 접근할 수 있는 title값 만을 바꿀 뿐, matrix객체가 접근할 수 있는 title에는 아무런 영향을 미치지 않음을 확인할 수 있다.


그래서 뭐 어따가 써먹음?

' private 변수 '

get_titleset_title이 내부적으로 사용하는 변수 title
외부함수factory_movie의 매개변수 title을 참조한다.

factory_movie함수는 객체return하면서 생이 마감하였기 때문에, get_titleset_title을 통해서만 title에 접근할 수 있다.

많은 data가 소프트웨어 내에서 존재하게 되는데 누구나 수정할 수 있는 형태의 데이터가 된다는 것은, 결국 그 소프트웨어가 망가질 가능성이 크다는 뜻이다.

이번의 경우 역시, get_titleset_title로만 title에 접근할 수 있기 때문에, 외부에서 title이라는 변수를 외부에서 어떻게 사용하든 간에 안전하게 유지할 수 있다.

또한 , 아래와 같이

function factory_movie(title) {
    return {
        get_title : function () {
            return title;
        },
        set_title : function(_title) {
          if (typeof _title === 'String') {
          	title = _title  
          } else {
            alert('제목은 문자열이어야 합니다.');
          }
        }
    }
}

조건을 생성해 주면, title 변수가 조금 더 안전하게 수정될 수 있다.


closure와 관련해 자주 언급되는 예제

여기에서 다룬 주제와 동일하다

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}

for (var index in arr) {
    console.log(arr[index]());
}

<실행결과>

5
5
5
5
5

아래의 코드로 변경해야 정상적으로 동작한다.

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(id) {
        return function(){
            return id;
        }
    }(i);
}

for(var index in arr) {
    console.log(arr[index]());
}

<실행결과>

0
1
2
3
4
profile
Blockchain Dev Journey

0개의 댓글