일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- flows
- Sieve_of_Eratosthenes
- dynamic programming
- BOJ
- CS Academy
- graph modeling
- hashing
- Euler circuit
- graph
- Segment Tree
- bitmask
- POJ
- Eulerian path
- GCD
- Dag
- scc
- BST
- backtracking
- disjoint-set
- BFSDFS
- Greedy
- Shortest path
- Cycle detecting
- 백준
- Eulerian circuit
- Algospot
- mathematics
- DynamicProgramming
- Euler path
- implementation
- Today
- Total
그냥 하는 노트와 메모장
Closure 본문
정의는 다음과 같다.
내부 함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는 함수의 형태를 클로저(Closure)라고 한다. |
실제 구현은 다음처럼 한다.
function outerFunction(param1){
var var1 = "ok";
function closure1(){
return var1 + param1;
}
return closure();
}
위에서 중요한건 outerFunction이 closure1를 호출했다는 사실보단 closure1라는 함수가 내부에 선언되었고, 이 안에 param1이나 var1 등의 outerFunction 컨텍스트에 존재하는 변수에 접근이 가능하단 사실이다. 하지만 외부에서는 closure1에 호출하려고 접근할 수 없다. 이러한 특성때문에 클로저를 특권 함수(privileged function)라고 부를 수 있다.
[Private 멤버]
자바를 공부해봤다면 접근제어지시자라는 용어를 들어봤을 수 있다. 자바스크립트에서는 이러한 접근제어지시자는 class와 #을 이용하여 내부 메서드를 제어할 수 있다(참고링크 : Javascript private class fields).
이 클로저 역시 이를 흉내낼 수 있다. 실제 사용할 객체을 정의하고, public으로 공개할 메서드는 객체 안에 선언하고 반대로 private로 공개하지 않을 메서드들을 모두 클로저로 두는 것이다.
function getMyObject(name){
function add(a, b) {
return a + b;
}
function div(a, b) {
return a / b;
}
function mul(a, b) {
return a * b;
}
function sub(a, b) {
return a - b;
}
return {
cal: function(a, b, op){
switch(op){
case '+': return add(a, b);
case '-': return sub(a, b);
case '*': return mul(a, b);
case '/': return div(a, b);
}
}
}
}
[Memory leak]
자바스크립트 엔진은 필요없는 메모리를 삭제하기 위해 가비지 컬렉터가 사용된다.
클로저를 사용할 때는 이에 유의해야한다. 아래의 코드를 보자.
var newElem;
function outer() {
var someText = new Array(1000000);
var elem = newElem;
function inner() {
if (elem) return someText;
}
return function () {};
}
setInterval(function () {
newElem = outer();
}, 5);
newElem 전역 변수에 outer()의 리턴값을 넣어주는 형태다. 이때 11번째 줄에 있는 함수가 반환이 되는데, inner 함수가 전혀 호출되지 않음에도 이 반환되는 함수와 컨텍스트를 공유하고 있기 때문에 inner는 메모리상에 있게 되고, 또 inner 함수는 elem을 참조하고 있으므로 이 메모리가 해제되지 않는다. 따라서 메모리 해제가 이뤄지지 못하고 남아있게 된다.
이 예제의 경우엔 함수 컨텍스트를 유지하게하지 못하게 하는 것이 핵심이다. newElem = outer()();로 함수를 호출해버림으로써 컨텍스트가 함수 호출로 끝나버리게 설정한다.