클로저 Closure

LEE GYUHO·2024년 7월 30일
0

클로저를 알기 전 알아야 하는 선행 지식

렉시컬 스코프(정적 스코프)

  • 변수의 유효 범위(scope)가 소스 코드 상에서의 위치에 의해 결정되는 스코핑 규칙
  • 함수를 어디에 선언 했는지에 따라 상위 스코프가 결정되는 것
function outer() {
    let outerVar = 'I am from outer';

    function inner() {
        console.log(outerVar);
    }

    inner();
}

outer(); // 출력: I am from outer

inner 함수는 outer 함수 내부에 정의되어 있다. inner 함수는 outerVar 변수를 참조할 수 있는데 이는 inner 함수가 선언된 위치가 outer 함수 내부이기 때문이다.

렉시컬 스코핑은 함수가 호출되는 위치가 아닌 정의된(선언된) 위치에 따라 스코프가 결정된다. 이때문에 inner 함수는 자신이 정의된 스코프(즉 outer 함수의 스코프) 내의 변수들에 접근할 수 있다.

클로저(Closure)

클로저란는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합이다.

정의가 어렵게 되어 있는데 내가 쉽게 이해한 바로는

  • 클로저란 자신이 선언된 당신의 환경을 기억하는 함수이다.
  • 클로저란 생명주기가 끝난 외부함수의 변수에 접근할 수 있는 내부함수이다.
  • (선언된 당시의 환경(렉시컬 스코프)을 기억하기 때문에 생명주기가 끝난 외부함수의 변수에 접근할 수 있는 함수)
function outerFunc() {
  // 외부 함수의 변수
  var x = 10;

  // 내부 함수에서 외부 함수의 변수에 접근할 수 있습니다.
  var innerFunc = function () {
    console.log(x);
  };

  return innerFunc;
}

var inner = outerFunc();
inner(); // 10

위 코드에서 outerFunc는 내부 함수 innerFunc를 return하고 생명 주기가 끝난 상태이다. (실행 후 콜스택에서 제거되었기 때문)
하지만 inner 함수를 호출하면 내부 함수 innerFunc가 실행되고 innerFunc는 선언된 당시 환경을 기억하고 있기 때문에 변수 x의 값이 10이 출력된다.

이와 같이 생명 주기가 끝난 외부 함수의 변수에 접근할 수 있는 함수를 클로저라고 한다.

클로저를 사용하는 이유

  1. 상태 유지

    클로저는 함수가 호출될 때마다 해당 함수의 렉시컬 환경을 기억하기 때문에, 함수 호출 간에 상태를 유지할 수 있다.
function debounce(callback, delay) {
  let timer = null;

  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      callback.apply(this, arguments);
    }, delay);
  };
}
  • 이 코드에서 익명 함수는 debounce 내에서 선언되었으므로 debounce 함수가 상위 스코프가 된다.
  • 함수는 선언된 환경의 주소를 기억하기 때문에 상위 스코프의 변수에 접근할 수 있게 되고, timer 변수에 접근할 수 있게 된다.
  • timer는 디바운스가 실행될 함수와 다른 스코프에 있기 때무에 timer에 대한 최신 상태를 유지할 수 있다.
  1. 데이터 은닉과 캡슐화

    클로저는 외부에서 직접 접글할 수 없는 비공개 변수를 생성하는 데 유용하다. 이를 통해 데이터 캡슐화가 가능해지고 전역 네임스페이스를 오염시키지 않으면서 데이터를 보호할 수 있다.
function makeCounter() {
    let count = 0;
    return function() {
        count++;
        return count;
    };
}

const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
profile
누구나 같은 팀으로 되길 바라는 개발자가 되자

0개의 댓글