해당 포스팅은 생활코딩의 이고잉 님의 강의를 기반으로 개인 공부용으로 정리한 포스팅임을 미리 알립니다.
자바스크립트 기본 문법 :: 내부함수
자바스크립트는 함수 안에서 또 다른 함수를 선언할 수 있습니다.
예시로 살펴보는 것이 더 쉬워요.
function outter(){
function inner(){
var title = 'test';
console.log(title);
}
inner();
}
outter();
위의 예제에서 함수 outter의 내부에는 함수 inner가 정의 되어 있습니다.
여기서 함수 inner를 내부 함수라고 하는 것 입니다.
내부함수는 외부함수의 지역변수에 접근할 수 있습니다.
function outter(){
var title = 'test';
function inner(){
console.log(title);
}
inner();
}
outter();
다시 위의 예제를 불러와볼게요.
실행시켜보면 아래 그림과 같이 test가 출력되는 것을 확인할 수 있습니다.
내부함수 inner에서 title을 호출(4행)했을 때
외부함수인 outter의 지역변수에 접근할 수 있음을 보여줍니다.
자바스크립트 기본 문법 :: 클로저(closure)란?
클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 말합니다.
클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용되기 때문에
알아두는 것이 좋습니다.
위에서 언급했던 것과 같이 내부함수는 외부함수의 지역변수에 접근 할 수 있는데,
외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도
내부함수가 외부함수의 변수에 접근 할 수 있습니다.
이러한 매커니즘을 클로저라고 합니다.
아래 예제는 이전의 예제를 조금 변형한 것입니다.
function outter(){
var title = 'test';
return function(){
console.log(title);
}
}
inner = outter();
inner();
예제의 실행순서를 주의하면서 보도록 하겠습니다.
7행에서 함수 outter를 호출하고 있습니다.
그 결과가 변수 inner에 담기고, 그 결과는 이름이 없는 함수입니다.
실행이 8행으로 넘어오면 outter 함수는 실행이 끝났기 때문에
이 함수의 지역변수는 소멸되는 것이 자연스럽습니다.
하지만 8행에서 함수 inner를 실행했을 때 test가 출력되는 것은
외부함수의 지역변수 title이 소멸되지 않았다는 것을 의미합니다.
결국 클로저란
내부함수가 외부함수의 지역변수에 접근 할 수 있고, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 의미합니다.
자바스크립트 기본 문법 :: Private Variable
Private 속성은 객체의 외부에서는 접근 할 수 없는 외부에 감춰진 속성이나 메소드를 의미합니다.
이를 통해서 객체의 내부에서만 사용해야 하는 값이 노출됨으로서 생길 수 있는 오류를 줄일 수 있습니다..
자바와 같은 언어에서는 이러한 특성을 언어 문법 차원에서 지원하고 있습니다.
자바에서는 private ~~ 형식으로 변수등을 선언하는 식으로 사용합니다.
클로저를 이용해서 영화의 제목을 저장하고 있는 객체를 정의하는 예제를 보겠습니다.
function factory_movie(title){
return {
get_title : function (){
return title;
},
set_title : function(_title){
title = _title
}
}
}
ghost = factory_movie('Ghost in the shell');
matrix = factory_movie('Matrix');
console.log(ghost.get_title());
console.log(matrix.get_title());
ghost.set_title('공각기동대');
console.log(ghost.get_title());
console.log(matrix.get_title());
위의 예제를 통해서 알 수 있는 것들을 정리해보면 아래와 같습니다.
클로저는 객체의 메소드에서도 사용할 수 있습니다.
위의 예제는 함수의 리턴값으로 객체를 반환하고 있는데,
이 객체는 메소드 get_title과 set_title을 가지고 있습니다.
이 메소드들은 외부함수인 factory_movie의 인자값으로 전달된 지역변수 title을 사용하고 있습니다.
동일한 외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유합니다.
17행에서 실행된 set_title은 외부함수 factory_movie의 지역변수인 title의 값을 '공각기동대'로 변경했습니다.
19행에서 ghost.get_title();의 값이 '공각기동대'인 것은
set_title와 get_title 함수가 title의 값을 공유하고 있다는 의미입니다.
똑같은 외부함수 factory_movie를 공유하고 있는 ghost와 matrix의 get_title의 결과가 서로 다르죠?
그것은 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문입니다.
따라서 ghost와 matrix는 서로 완전히 독립된 객체가 되는 것 입니다.
factory_movie의 지역변수 title은 2행에서 정의된 객체의 메소드에서만 접근 할 수 있는 값입니다.
이 말은 title의 값을 읽고 수정 할 수 있는 것은
factory_movie 메소드를 통해서 만들어진 객체 뿐이라는 의미와 같습니다.
JavaScript는 기본적으로 Private한 속성을 지원하지 않는데,
클로저의 이러한 특성을 이용해서 Private한 속성을 사용할 수 있게 되는 것 입니다.
이 클로저 특성을 응용해서 자주 실수하는 경우도 알아보도록 하겠습니다.
var arr = []
for(var i = 0; i < 5; i++){
arr[i] = function(){
return i;
}
}
for(var index in arr) {
console.log(arr[index]());
}
위의 예제의 결과 값이 어떻게 될까요?
함수가 함수 외부의 컨텍스트에 접근할 수 있을 것으로 기대하겠지만 위의 결과는 아래와 같습니다.
0부터 4까지 정상적으로 출력하고 싶다면, 아래 예제와 같이 코드를 작성해야합니다.
var arr = []
for(var i = 0; i < 5; i++){
arr[i] = function(id) {
return function(){
return id;
}
}(i);
}
for(var index in arr) {
console.log(arr[index]());
}
사실 이 클로저라는 개념이 개발을 이제 막 시작하신 분들에게는
복잡하고 어려워 보일 수 있지만,
초급 개발자를 벗어난 중급, 더 나아가 고급까지 가실 분들은 반드시 알고 가야할 개념이기도 합니다.
아래는 클로저 개념을 더 잘 이해하기 위한 참고 링크입니다.
- https://developer.mozilla.org/ko/docs/JavaScript/Guide/Closures
- http://ejohn.org/apps/learn/#48
- http://blog.javarouka.me/2012/01/javascripts-closure.html
'Archive > Develop' 카테고리의 다른 글
[ JavaScript ] 자바스크립트 기본 문법 | 함수의 호출(apply) (0) | 2021.02.04 |
---|---|
[ JavaScript ] 자바스크립트 기본 문법 | 자바스크립트 arguments | function length (0) | 2021.02.03 |
[ JavaScript ] 자바스크립트 콜백 & 비동기처리 (0) | 2021.02.03 |
[ JavaScript ] 자바스크립트 함수 지향 | 메소드와 함수 차이 | 함수 리턴값 | 함수 배열 (0) | 2021.02.03 |
[ JavaScript ] 자바스크립트 전역변수와 지역변수 | 변수의 유효범위 (0) | 2021.02.03 |