[JavaScript] Closure(코어 자바스크립트)

link717·2020년 11월 29일
0

JavaScript

목록 보기
15/17
post-thumbnail

🌼 Closure

클로저(Closure)는 내부함수가 외부함수의 맥락(Context)에 접근할 수 있는것으로 어떤 함수 A에서 선언한 변수 A를 참조하는 내부함수 b를 외부로 전달한 경우, A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상을 말한다.

  • 내부함수는 외부함수의 지역변수에 접근할 수 있다.
  • 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근할 수 있다.
 function outter() {                         // 외부 함수
   var title = 'coding everybody';           // 외부 함수의 지역변수
   function inner() {                        // 내부 함수
     alert(title);
   }
   inner();
 };

inner = outter();  // outter는 내부함수를 return 했기 때문에 함수로써의 기능이 끝난것이다.
inner();           // 하지만 inner를 호출하면 title이라는 외부함수의 변수에 접근이 가능하다.

  • 매개변수(argument)는 함수 내부에서 지역변수로 사용된다.
  • title이라는 argument에 접근을 get_title 혹은 set_title을 통해서만 할 수 있을 때 data의 encapsulation이 가능하며 private한 변수로서의 기능을 하게된다.
function factory_movie(title){
  return {
    get_title : function() {
      return title;
    },
    set_title : function(_title) {
      if (typeof _title === 'String') {
        title = _title
      } else {
        alert('제목은 문자열이어야 합니다.');
      }  
    }
  }
}

ghost = factory_movie('Ghost in the shell');
matrix = factory_movie('Matrix');

🌻 클로저와 메모리 관리

메모리 누수라는 표현은 개발자의 의도와 달리 어떤 것의 참조 카운트가 0이 되지 않아 Garbage Collector의 수거 대상이 되지 않는 경우이다. 만약 개발자의 의도와 상관없이 메모리 누수가 예상된다면 참조카운트를 0으로 만들어 GC의 수거 대상으로 만들어주면 된다.

// 식별자에 참조형이 아닌 기본형 데이터를 할당하는 방법
let outer = (function() {
  let a = 1;
  let inner = function() {
    return a++;
  }
  return inner;
})();

console.log(outer());  // 1
console.log(outer());  // 2
outer = null;

🌻 클로저 사용시 주의점

  • 예상은 0,1,2,3,4가 출력될 것이라고 생각했으나 5가 5번 출력된다.
  • for문을 끝내기 위해서는 i = 5 인 경우가 실행이되는데 그 때의 i를 전역변수로 참고하여 에상과 다른 값이 출력된 것이다.
let arr = []
for(let i = 0; i < 5; i++){
  arr[i] = function(){
    return i;
  }
}

for(let index in arr) {
  console.log(arr[index]());
}

 (5) 5
  • 예상대로 0 ~ 4까지가 호출된다.
  • arr[i]는 IIFE로 함수를 즉시 호출하는 방식을 사용하였다. (IIFE는 global scope를 오염시키지 않기 위해 사용한다.)
  • 내부 함수는 i라는 전역변수를 id로 받아 id를 return 하므로써 결국에는 내부 함수에 id라는 지역변수를 만들었다. 그리고 그 값들을 즉시 호출하는 방식을 통해 return 하였기 때문에 우리가 예상한대로 값이 출력된 것을 알 수 있다.
let arr = [];
for(let i = 0; i < 5; i++) {
  arr[i] = function(id) {
    return function(){
      return id;
    }
  }(i);  
}

for(let index in arr) {
  console.log(arr[index]());
}0, 1, 2, 3, 4
profile
Turtle Never stop

0개의 댓글