# 클로저(closure)
- 범위체인 (scope chain)
자바스크립트의 범위에는 중괄호 범위가 아닌 함수범위가 존재한다. (ES6부터는 let, const 키워드 도입으로 블록단위 사용가능)
예) - 클로저는 해당 함수에대한 환경을 기억한다, 자바스크립트는 객체단위이다
예)
a() 를 두번호출한 후 b() 를 호출하면 addOne() 의 함수이름이 같기때문에
b() 의 호출값은 3 이 되어야 맞지만 1 이 출력된다
그 이유는 변수 a 와 변수 b 는 다른 객체이기 때문에 서로 다른 환경을 가지고 있다.
루프의 클로저
클로저는 외부함수의 변수에대한 참조를 기억한다
예)
예상한 결과와 다르게 나온다, 그 이유가 무엇일까?
함수는 값을 기억하지 못하고, 생성된 환경에대한 참조(링크)만 기억한다
그렇기때문에 함수들에대한 참조값은 최근 값인 i 의 3 이 된다.
왜 2 가 아니라 3 이 나오는지 궁금하면, for 루프의 순서를 생각해보면 될 것이다
그렇다면 원하는 값을 나오게하려면 어떻게 할것인가?
함수는 생성된 환경에대한 참조만 기억한다고 했다
즉시실행함수 내에 익명함수를 클로저로 만들어 i 가 x 로 전달이되고
클로저에의해 각기 다른 환경에 저장된다.
사실 ES6부터는 let , const 가 도입된 후로 간단히 let 으로 바꾸면된다
결과가 동일한 이유는 let 의 scope 에 대해 생각해보면 될 것이다.
let 을 foo() 함수 맨위에 선언 후 실행하면 어떻게될까?
기대한 값이 나오지 않는다. 그이유는 let 은 블록범위를 가지기 때문에 함수의 범위 안에 있게된다
그렇다면 var 을 for 문 안에 넣으면 되지않느냐?
이 또한 기대한 값이 나오지 않는다. 그 이유는 var 선언은 scope 가 함수로 정해져있기 때문이다.
다른 방법도 있다. 내부함수를 이용하는것이다
예)
결과는 동일하다
- 클로저를 통한 은닉 (getter, setter)
변수를 함수에 은닉할 수 있다
대신 추가함수 두개가 필요하다
예)
즉시실행함수를 통해 getValue 와 setValue 에 함수가 할당된다
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/
'복습 > Javascript' 카테고리의 다른 글
[Javascript] 객체지향 자바스크립트 [객체 part 2] (0) | 2018.02.08 |
---|---|
[Javascript] 객체지향 자바스크립트 [객체 part 1] (0) | 2018.02.08 |
[Javascript] 객체지향 자바스크립트 [함수는 데이터, 콜백함수, 함수반환, 내부함수] (0) | 2018.02.06 |
[Javascript] 객체지향 자바스크립트 [함수, 호이스팅, 블록범위] (0) | 2018.02.06 |
[Javascript] 객체지향 자바스크립트 [조건문, 반복문, 주석] (0) | 2018.02.05 |