완로그
article thumbnail

Closure

함수가 선언될 때의 유효 범위(렉시컬 범위)를 기억하고 있다가,

함수가 호출될 때 그 유효 범위의 특정 변수를 참조할 수 있는 개념을 의미한다.

쉽게 말하면, 자신이 선언될 당시의 환경을 기억하는 함수이다.

 

데이터를 보존하고, 접근을 제한하고, 모듈화에 유리하다는 장점이 있다.

 

그렇다면 클로저의 예시를 살펴보자.

// Closure

function createCount() {
  let cnt = 0;
  return function () {
    return (cnt += 1);
  };
}

const c1 = createCount();
console.log(c1()); // 1
console.log(c1()); // 2
console.log(c1()); // 3

const c2 = createCount();
console.log(c2()); // 1
console.log(c2()); // 2
console.log(c2()); // 3

클로저를 사용하게 되면 카운트를 위한 전역 변수를 따로 만들어주지 않아도 된다.

 

프론트엔드 개발에서는 이용되는 클로저의 개념에는 어떤 것이 있을까?

먼저, 클로저를 사용하지 않은 예시이다.

const h1 = document.querySelector("h1");
const h2 = document.querySelector("h2");

// 별도의 상태 관리 필요!!
let h1IsRed = false;
let h2IsRed = false;

h1.addEventListener("click", (e) => {
  h1IsRed = !h1IsRed;
  h1.style.color = h1IsRed ? "red" : "black";
});

h2.addEventListener("click", (e) => {
  h2IsRed = !h2IsRed;
  h2.style.color = h2IsRed ? "red" : "black";
});

같은 로직을 수행하기 위해 두 개의 전역 변수를 사용하고 있다.

요소가 늘어나면 상태를 관리할 수 있는 변수 역시 그만큼 늘어날 것이다.

 

그렇다면, 클로저를 사용하면 어떻게 달라질까?

const h1 = document.querySelector("h1");
const h2 = document.querySelector("h2");

const toggleIsRed = () => {
  let isRed = false;
  return (e) => {
    isRed = !isRed;
    e.target.style.color = isRed ? "red" : "black";
  };
};

h1.addEventListener("click", toggleIsRed());
h2.addEventListener("click", toggleIsRed());

클로저를 사용하면 요소가 늘어나더라도, 상태를 관리하는 전역 변수를 선언할 필요가 없어진다.

profile

완로그

@완석이

프론트엔드 개발자를 꿈꾸는 완석이의 일기장입니다.