본문 바로가기

복습/Javascript

[Javascript] 객체지향 자바스크립트 [클로저]

# 클로저(closure)


  • 범위체인 (scope chain)

        자바스크립트의 범위에는 중괄호 범위가 아닌 함수범위가 존재한다. (ES6부터는 let, const 키워드 도입으로 블록단위 사용가능)

                예)
                        


  • 클로저는 해당 함수에대한 환경을 기억한다, 자바스크립트는 객체단위이다

            예)

                
                
                a()
    를 두번호출한 후 b() 를 호출하면 addOne() 의 함수이름이 같기때문에
                b() 의 호출값은 3 이 되어야 맞지만 1 이 출력된다
                그 이유는 변수 a 와 변수 b다른 객체이기 때문에 서로 다른 환경을 가지고 있다.


    • 루프의 클로저

              클로저는 외부함수의 변수에대한 참조를 기억한다

              예)

                  

                  

                  예상한 결과와 다르게 나온다, 그 이유가 무엇일까?

                  함수는 값을 기억하지 못하고, 생성된 환경에대한 참조(링크)만 기억한다

                  그렇기때문에 함수들에대한 참조값은 최근 값인 이 된다.
                  왜 2 가 아니라 3 이 나오는지 궁금하면, for 루프의 순서를 생각해보면 될 것이다
                  그렇다면 원하는 값을 나오게하려면 어떻게 할것인가?

                  함수는 생성된 환경에대한 참조만 기억한다고 했다


                  

                  

                  즉시실행함수 내에 익명함수를 클로저로 만들어 ix 로 전달이되고
                  클로저에의해 각기 다른 환경에 저장된다.


                  사실 ES6부터는 let , const 가 도입된 후로 간단히 let 으로 바꾸면된다


                  

                  

                  결과가 동일한 이유는 let 의 scope 에 대해 생각해보면 될 것이다.
                  let foo() 함수 맨위에 선언 후 실행하면 어떻게될까?

                  

                  

                  

                  기대한 값이 나오지 않는다. 그이유는 let 은 블록범위를 가지기 때문에 함수의 범위 안에 있게된다
                  그렇다면 varfor 문 안에 넣으면 되지않느냐?

                  

                  
                  
                  
                  이 또한 기대한 값이 나오지 않는다. 그 이유는 var 선언은 scope 가 함수로 정해져있기 때문이다.
                  다른 방법도 있다. 내부함수를 이용하는것이다

                  예)
                  

                  

                  

                  결과는 동일하다


  • 클로저를 통한 은닉 (getter, setter)

            변수를 함수에 은닉할 수 있다
            대신 추가함수 두개가 필요하다

            예)

            
            
 
            즉시실행함수를 통해 getValuesetValue 에 함수가 할당된다
            getValue 는 함수 내부의 priv 를 return 해준다
            setValue 는 값을 설정해 내부의 priv 를 설정해준다
            이렇게 데이터의 은닉이 가능하


  • 클로저의 성능

            클로저는 각자의 환경을 가진다고 했다, 그렇다면 어쨌든 메모리를 소모한다는 말인데
            클로저를 이용하고 나서 제거를 해주지 않으면 가비지컬렉션(garbage collection) 에 의해
            제거되지 않는다, 사용을 한후에 null 값으로 지워주도록 하자









[참고]
        https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures
        http://meetup.toast.com/posts/86
        https://hyunseob.github.io/2016/08/30/javascript-closure/