[JS] 클로저

heyhey·2023년 4월 11일
0

JavaScript

목록 보기
14/14
  • 클로저에 대해 겁이 많았었는데, 이번에 공부를 해보며 원리와 이해를 하도록 한다.

클로저란

클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경의 조합입니다.

쉽게 말해 함수 내부에서 선언한 변수와 함수들은 해당 함수 외부에서 접근할 수 없습니다.

하지만 함수 내부에서 선언한 변수를 참조하는 함수가 반환될 경우, 그 함수와 변수들을 함께 기억하고 있는 것을 클로저라고 합니다.

(함수를 만들었는데, 안의 변수들을 접근할 수 없다 . 대신 함수를 반환할 때, 그 함수에서는 변수들을 기억하고 있는다.)

예시 코드를 통해 개념을 보겠습니다.

function outerFunc(){
	const outerVar = 'OUTER';
  	function innerFunc(){
    	const innerVar = "INNER"
        console.log(outerVar + innerVar);
    }
	return innerFunc;
}
const inner = outerFunc();
inner() // OUTER INNER

outerFunc는 innerFunc 함수를 반환합니다.
이 때 outerFunc 함수가 실행될 때 생성된 렉시컬 환경에서는 outerVar 변수를 참조합니다.
따라서 outerFuc 함수가 실행되고 종료될 때도 outerVar 변수의 값은 유지됩니다.

원래라면 함수가 종료되면 변수가 없어진다고 볼 수 있는데, innerFunc이 inner 로 저장되어 있기 때문에, 계속해서 outerVar를 참조할 수 있습니다.

const inner = outerFunc();
위 함수가 먼저 실행되기 떄문에, 함수가 이미 종료된 이후 입니다.
그러나 클로저 덕분에, inner() 를 통해 innerFunc 함수 내부에서는 outerVar 변수를 참조할 수 있습니다.


다른 예시를 들어보겠습니다.

function createCounter() {
  let count = 0;
  return function() {
    count++
    return count
  };
}
counter = createCounter()
a = counter() // a => 1 
b = counter() // b => 2
c = counter() // c => 3

위 예시 코드에서는 createCounter 함수가 호출될 때마다 count 가 초기화되면서, 익명 함수가 반환됩니다.

  • createCounter 함수가 실행되면 새로운 렉시컬 환경이 생성됩니다.
  • 각각의 렉시컬 환경은 자신만의 count 변수를 갖고 있습니다.
  • 익명 함수가 반환되면서 클로저가 생성됩니다.
  • 이 클로저는 createCounter 함수의 렉시컬 환경과 익명 함수가 참조하는 count 변수를 함께 기억합니다.

사용 예시

  1. 이벤트 핸들러

클로저는 이벤트 핸들러에서 많이 사용됩니다.
이벤트 핸들러 함수는 외부 스코프에 정의된 변수에 접근해야 하는데, 이 때 클로저를 사용하여 해당 변수에 접근할 수 있습니다.

function createCounter() {
  let count = 0;
  document.getElementById("button").addEventListener("click", function() {
    count++;
    console.log(count);
  });
}

createCounter();
  1. 비동기 콜백 함수

비동기 콜백 함수에서도 클로저가 사용됩니다. 비동기 함수 내부에서 참조하는 변수가 비동기 함수가 반환된 이후에도 유지되어야 하는 경우에 클로저를 사용합니다.

function createCounter() {
  let count = 0;
  setTimeout(function() {
    count++;
    console.log(count);
  }, 1000);
}

createCounter();
  1. 데이터 은닉화
    객체의 속성을 직접 접근하는 것을 방지하기도 하고, 메소드를 통해 간접적으로 속성에 접근할 수도 있습니다.
function createCounter() {
  let count = 0;
  return {
    getCount: function() {
      return count;
    },
    increment: function() {
      count++;
    }
  };
}

const counter = createCounter();
console.log(counter.getCount()); // 0
counter.increment();
console.log(counter.getCount()); // 1

클로저는 함수 내부에서 사용되는 변수를 함수가 반환된 이후에도 계속해서 사용할 수 있도록 만들어주는 것입니다. 이를 가능하게 하는 것은 함수가 선언됐을 때의 환경을 기억하고 있기 때문입니다. 따라서, 클로저는 함수를 둘러싼 스코프의 변수를 "캡처"하여, 해당 변수를 함수 외부에서도 계속해서 사용할 수 있도록 해줍니다.

profile
주경야독

0개의 댓글