Javascript – scope 이야기 클로저(Closure) – 내가 보는 클로저 1/2
클로저는 이처럼 특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게하는 폐쇄성을 갖는다.
(구글에서 검색한 결과중 가장 간결하게 표현한 글이어서 퍼왔다.)
간단히 살펴보는 변수의 일생
}
var isName = myFuncton(“dog”);
console.log(myFunction(isName)); // i’m a dog 를 출력한다.
console.log(_name); // undefined 오류 발생 / 너무 당연
너무 간단한 함수이다. 하지만, 함수 보다 지역변수 _name 에 대한 이야기 해보려한다.myFunction 이 호출되기전까지
_name 변수는 어디에도 없는 변수이다.
myFuncton(“dog”); 이 호출됨과 동시에,
myFunction() 이 호출되면서 var _name 변수가 정의 되어지고 , 호출 되면서 넘겨진
“dog” string 을 _name 에 “i am a ${name}” 을 할당하고 _name 을 리턴, _name 변수은 소멸되게 된다. 정확한 소멸 시점은
myFunction() 함수의 브레이스가 { ~ } 닫히는
시점이고 그 전까지 변수는 메모리에 그대로 유지된다. (모든 프로그램이 그렇다)
var isName = myFunction(“dog”);
여기서 isName 은 myfunction 내부에 정의 되었던 변수 _name 의 값을 리턴받아
마치 _name 을 그대로 사용하는겉 같은 효과를 볼 수 있다.
하지만 isName 변수는 myFunction() 의 _name 과 완전히 다른 변수라는것을 이미 알고있을 것이다. 이것이 일반적인 변수의
scope 내에서 일어나는 일이다.
그런데 만약, _name 변수를 , myFunction 함수가 소멸됨과 동시에 사라지지않고
외부에서 계속 사용할 수 있는가에 대한 이야기 이다.
클로저(closure)
클로저를 처음 접했을때 단순 함수에서의 지역변수(호출되는 함수의) 리턴 값에 대한 이야기 인줄알았다. 하지만 위에 개념에서 설명하듯
Javascript의 함수내에 정의된 변수가 외부에서 그 변수를 접근할 수 있냐는 것에 대한 것이다.
좀 더 정확히 이야기 하자면, _name 의 소멸에 관한 이야기 이다.
아래 코드를 보자
}
// 변수 getFn 은 myFunction 에서 함수로 리턴을 했기때문에 fnGetMyName 함수
// 밖에서도 함수의 역할을 그대로 할 수 있다.
var getFn = myFunction(“dog”);
console.log(getFn());
맨 위에 _name 소멸과정을 개념으로 펴보자면,
마지막 console.log(getFn()); 에서는 _name 변수 내용을 출력하는데,,
사실 이 부분은 문제가 발생하거나, 내부 함수 fnGetMyName 에서 변수가 _name 이
아니면, 반대로 그냥 당연해 보이는 자연스러운이 느껴질수도있다.
하지면 변수의 scope 개념을 다시 이해한다면 조금 이상하게 느껴진다.
myFunction() 호출시점 var getMyFunction = myFunction(“dog”); 에서 _name 변수가 선언되고 , _name = `i am a ${s}` 이 할당되어 사용이 되어진다.
그리고 myFunction 브레이스가 } 닫히면서 _name 변수(함수 모두)가 소멸되게 된다.
즉, getFn() 함수는 ( getFn() = fnGetMyname() ) 이미 소멸한 _name 의
값을 출력하고있는 것이다.
소멸되지 않은 함수와 변수
호출시 리턴되어, 외부에서 사용되기 때문에 fnGetMyName() 함수를 소멸 시키지 않는다.
2) _name 변수 또한 내부 함수 fnGetMyName() 에서 사용하고 있기때문에
myFunction() 함수가 끝나는 시점에 _name 변수도 소멸되지않는다.
(_name 을 fnGetMyName() 내부함수에서 사용하지 않으면 소멸된다.)
( fnGetMyName() 함수는 _name 변수를 참조한다. = 연결되어있다)
* 여기서 한 번더 집고 넘어갈 개념_name 과 fnGetMyname() 함수는 복사되어 getFn() 를 만드는것이 아니라,
서로 참조에 의해 연결되어 있다는 것이 중요하다.
그 원리는 address 로 접근하여 바라보는 참조와 유사하다는 느낌이들었다.
내가알고는 개념에서는 변수가 가지고 있는 메모리상의 주소를 참조하는 참조 느낌을강하게 받았다.)만약 fnGetMyName() 함수의 구현이 메모리 0x0000:1111 번지에 구현되어 있다면,
getFn() 함수도 똑같이 0x0000:1111 번지 구현 부분을 바라보고 있다는것이다.
getFn() 은 fnGetMyName() 을 참조하고 fnGetMyName() 은 _name 을 참조하고
*이렇듯 외부함수의 변수를 함수(외부)가 소멸한 뒤에서 계속 참조하기 위해서는 내부함수에서는
외부함수의 변수를 접근하는 방식으로 코딩하여야한다.
(아다시피,, 직접 변수를 return 하면 값만 리턴되므로,,,,)
* 전역 변수로 살아 있는 상태로 메모리에 존재하기 때문에 GC 에의 수집되지
않으므로 사용수 정리가 반드시 필요하다 , getFn = null
이제 상단에 정의한 개념을 다시 살펴보고 정리하자
클로저 함수는 외부 함수(myFunction) 의 실행이 끝나더라도 외부 함수(myFunction) 내 변수(_name)를 사용할 수 있다.
클로저(myFunction 함수가 종료하여 변수와 함수가 소멸되지기전 환경이 그대로 유지되는것
– 즉 fnGetMyName( 함수가 소멸되지않고 fnGetMyName() 함수에서 외부함수에 선언된 _name 변수를
사용하는 바람에 그것도,,, 소멸시킬수 없는 상태 = 클로저(폐쇄)상태) 는
이 처럼 특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게하는 폐쇄성을 갖는다.