javascript closure 자바스크립트 클로저의 개념 쉽게 이해. 클로저란?
자바스크립트 하면 빠지지 않는 것 중에 하나가 클로저(Closure) 입니다.
하지만 이것을 사용하지 않는다고 해서 개발을 못하진 않죠. 그렇다고 몰라도 되는 개념은 아닙니다.
클로저의 정의는 매우 다양합니다. 이 책에서는 이렇게 저 책에서는 저렇게 정의 하죠.
예를 들면
'클로저는 내부함수가 외부함수에 context에 접근 할 수 있는 것을 가르킨다.'
'생명주기가 끝난 객체에 접근할수 있는 것 이다'
'외부함수의 실행이 끝나서 소멸된 후에 내부함수가 외부함수에 변수에 접근하는 매커니즘이다.'
뭐 다 처음에는 뭔데? 하는 생각만 들죠.
여러가지 예를 보면서 이해하는 방법 밖에 없습니다.
자바스크립트의 스코프에 대한 이해가 있다면 그냥 '생명주기가 끝난 변수에 접근하는 함수' 쯤으로 느끼고 넘어가죠.
첫번째 예 입니다.
$(function(){
var outer = 2;
var addTo = function(){
var inner = 3;
return outer + inner;
}
console.log(addTo());
});
매우 간단하죠.
addTo라는 함수는 그 함수의 내부에 있는 inner변수와 함수 밖의 outer변수의 합을 구해 리턴 하죠.
그래서 addTo() 함수를 실행하면 5가 찍히게 되죠.
여기서 addTo 익명함수 가 클로저에요. addTo함수 내에는 outer가 없는데 그 값에 접근 해서 합을 구했죠??
기본적으로 자바스크립트에서는 함수내에서는 함수 내에 있는 지역변수에만 접근이 가능하죠.
하지만 호출한 변수가 없을 경우에는 스코프체인에 의해 그 밖에서 찾게 됩니다.
여기서는 함수 내 지역변수에 outer가 없기 때문에 그 밖 전역변수에서 outer를 찾은 거죠!
그래서 에러 없이 5 가 출력이 되는 것입니다.
그럼 정말 outer가 클로저인지 확인 해보죠. 위의 console.log(addTo()); 를 console.dir(addTo); 로 수정한 후
실행합니다. F12를 눌러 console창을 확인해 봅니다. (크롬브라우져로 하세염)
addTo Function에 [[Scopes]] 에 Closure 가 있죠!!!! 그리고 그 내에 outer 가 있습니다. 클로저 맞죠?
그럼 다음 예를 보겠습니다.
$(function(){
var outer2Value = 4;
function outer(){
var outerValue = 3;
return function(){
var innerValue = 2;
console.log(innerValue+outerValue+outer2Value);
}
}
var inner = outer();
console.dir(inner);
inner();
});
첫 예보다 조금 아주 조금 복잡합니다.
outer함수를 inner라는 변수에 담고 (inner는 리턴되는 익명함수가 되겠죠..)
그것을 실행하는 코드 입니다.
여기서도 클로저가 존재하죠. 첫번째 예를 이해하셨다면 바로 나오실겁니다.
리턴되는 익명함수가 클로저이고,
outerValue와 outer2Value가 자유변수죠. 확인해볼까요?
outer() 함수는 innerValue, outerValue, outer2Value의 합을 구하는 함수를 리턴 합니다.
그러니 var inner = outer(); 에서 inner는 outer내의 익명함수가 되겠죠.
하지만 리턴되는 함수 내에는 innerValue만 있을 뿐 outerValue와 outer2Value는 존재하지 않습니다.
첫번째 예제와 같이 스코프 체인에 의해서 접근, 접근 하게 되는 것이죠.
내부함수(inner)에 없네? 외부함수(outer)를 함 볼까? 어 없네? 그럼 전역변수를 봐야겠다. 이거죠.
이런식으로 찾아가게 됩니다.
Closure의 뜻은 '폐쇠' 죠. 하지만 역으로 Closure를 통해 폐쇠된 범위 밖의 객체에 접근 할 수 있습니다.
예를 들어 아래의 예를 보도록 하겠습니다.
$(function(){
function fn(){
var name = 'geon';
this.getName = function(){
return name;
}
}
var newFn = new fn();
console.log(newFn.name);
console.log(newFn.getName());
console.dir(newFn);
});
console.log(newFn.name); 의 결과는 undefined 입니다. 비공개 객체 이기 떄문에 바로 접근은 불가하죠.
하지만 console.log(newFn.getName()); 의 결과는 geon 입니다. 클로저의 범위 내의 변수는 생성자 함수 외부에 노출되지 않지만 객체의 공개 메소드 내에서는 접근 할 수 있습니다.(this.getName())
즉, 생성자에서 객체를 반환할때 비공개 변수를 사용하는 메서드를 정의하면 이 메서드 안에서는 클로저가 발동해 그 비공개 변수에 접근 할 수 있는 것이죠.
가장 아래 console.dir(newFn); 를 추가하여 확인해 보면 getName은 있지만 name변수는 없는 것을 확인 하 실 수 있습니다.
그럼 마지막으로 클로저의 개념을 이해했는지 문제를 하나 보도록 하죠.
function outer(a, b){
var c = 3;
return function(d){
console.log(a+b+c+d);
}
}
var inner = outer(1,2);
inner(4);
의 실행 결과는 무엇일까요?
var inner = outer(1,2); 에서
function(d){
console.log(1+2+3+d);
}
가 리턴이 됩니다. 여기서 c가 클로저가 되겠죠.
그리고 inner(4); 가 실행이 되면서 d에 4가 매핑이 되죠.
function(d){
console.log(1+2+3+4);
}
결과는 10 입니다.
엄청난 장점 이기도 하지만 메모리의 부담이 느는 단점이 있죠.
뭐든 그렇겠지만 잘 사용하는 것이 중요합니다.
그것은 경험으로 얻어질 것이라 생각합니다.
다음 포스팅에서는 클로저를 사용할때 주의해야 할 점을
다른 예들을 통해서 알아보도록 하겠습니다.
Link : 클로저 사용시 주의할 점. 클로저 유의사항, 반복문, 실행시점
'Programing > JavaScript' 카테고리의 다른 글
Javascript prototype 프로토타입 이란? prototype을 사용하는 방법을 알아보자. (1) | 2017.05.30 |
---|---|
클로저 사용시 주의할 점. 클로저 유의사항, 반복문, setInterval, 실행시점 (0) | 2017.05.25 |
javascript sort 자바스크립트 배열 정렬 방법 오름차순 내림차순 (0) | 2017.05.23 |
javascript this 알짜만 빼먹기! this 마스터! (0) | 2017.05.22 |
javascript 이번달 시작일, 말일 구하기 (0) | 2017.03.30 |
댓글