functionoutterFunc() { // 외부함수 var title = 'lalala'; functioninnerFunc() { // 내부함수 alert(title); } innerFunc(); }
어떠한 함수가 있는데, 그 함수 안에서만 사용되는 함수가 있다. 이것을 내부함수로 선언한다면 , 가독성을 높이고 오류 가능성을 줄일 수 있다.
그리고 이때, 내부함수에서 외부의 함수의 지역변수에 접근 할 수 있는데 이것을 클로저(Closure)라고 한다.
외부함수가 더 이상 사용되지 않는 경우에도, 내부함수가 외부함수의 지역변수에 접근할 수 있다.
1 2 3 4 5 6 7 8 9
functionoutterFunc() { // 외부함수 var title ='외부함수의 지역변수'; returnfunction() { // 내부함수 console.log(title); } }
var innerFunc = outterFunc(); innerFunc(); // 외부함수의 지역변수
내부 함수를 리턴함으로서, 외부함수가 사라졌음에도 불구하고, 외부함수의 지역변수에 접근이 가능하다.
아래 코드를 보자.
1 2 3 4 5 6 7 8 9
var arr = []; for (var i = 0; i < 5; i++) { arr[i] = function() { return i; } } for (var index of arr) { console.log(arr[index]()); // 5 5 5 5 5 }
만약 결과를, 0 1 2 3 4 가 나오도록 바꾸고 싶다면. 클로저를 사용해야 한다.
1 2 3 4 5 6 7 8 9 10 11
var arr = []; for (var i = 0; i < 5; i++) { arr[i] = function(id) { // 외부 함수를 익명함수로 선언후 인자를 넘겨 바로 실행 returnfunction() { // 내부 함수를 리턴 return id; } } (i); } for (var index of arr) { console.log(arr[index]()); // 0 1 2 3 4 }
arr[0]의 외부함수의 지역변수는 실행당시 맥락(i=0)을 유지하고 있는다.
클로저의 구조
클로저로, 외부 함수의 스코프 변수에 접근 가능한 이유는, 내부 함수의 스코프 체인에 외부함수의 스코프가 포함되기 때문이다.
1 2 3 4 5 6 7 8 9 10
functioncCompFunc(pName) { returnfunction (o1, o2) { var v1 = o1[pName]; var v2 = o2[pName]; return v1 - v2; } }
var compare = cCompFunc('name'); var result = compare({name:'Junho'}, {name: 'JJong'});
cCompFunc(외부함수)가 실행을 마치고 익명함수를 반환
익명함수의 스코프 체인에는 외부함수의 활성화 객체, 전역함수가 포함
익명함수는 외부함수의 변수 전체에 접근
익명함수의 스코프 체인에서 외부함수를 참조하고 있기 때문에, 외부함수의 활성화 객체는 가비지 컬렉션의 대상이 되지 않는다.
내부 함수는 외부함수 변수에 저장된 마지막 값만 알 수 있음.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
functioncreateFunc() { var result = []; for(var i = 0; i<10; i++) { result[i] = function() { return i; } } return result; } var a = createFunc(); a[0](); //
a[0](); // 10 a[1](); // 10
모든 함수가 10을 반환, 모든 함수가 createFunc()의 활성화 객체의 같은 변수 i를 참조한다.
수정 버젼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
functioncreateFunc() { var result = []; for(var i = 0; i<10; i++) { result[i] = function(num) { returnfunction() { return num; }; }(i); } return result; } var a = createFunc();
a[0](); // 0 a[1](); // 1
function 함수를 한번 더 감싸고, 실행시킴으로써, num에는 i자체가 아니라 값이 복사되어 들어오게 된다. 내부함수에는 복사된 제각기 다른 num을 가지게 되어 의도한대로 값을 출력할 수 있다.
클로저의 this 객체
this객체는 런타임에서 함수가 실행 중인 컨텍스트 객체를 가리킨다.
1 2 3 4 5 6 7 8 9
var name = "Window"; var obj = { name: "Obj", getNameFunc: function() { returnfunction() { returnthis.name; } } }; alert(obj.getNameFunc()); // Window
익명함수는 외부 함수의 this**객체를 직접**적으로 접근할 수 없다.
수정 버젼
1 2 3 4 5 6 7 8 9 10 11
var name = "Window"; var obj = { name: "Obj", getNameFunc: function() { var that = this; returnfunction() {