JavaScript - Closure

김철회·2022년 8월 3일
0

Closure

먼저 이 말을 생각하고 Closure에 접근하자!

다른 언어는 함수의 값을 리턴 하면 함수 내부의 변수가 사라지는데, 자바스크립트는 클로저에 의해서 내부의 변수가 사라지지 않고 참조할 수 있게 된다.(정확히는 함수형 프로그래밍 언어에서 사용 된다.)

Closure는 공부하면 할수록 정말 어려운 개념이었다. scope와 실행컨텍스트에 대한 개념도 같이 알고 있어야만 이해가 그나마 조금 되었기 때문이다.(사실 지금도 크게 와닿지 않지만..)

다시 Closure에 대해 알아보자!

클로저는 주변의 상태 (lexical environment)의 참조와 함께 번들로 묶인 함수의 조합입니다. 즉, 클로져는 우리에게 inner함수에서 outer함수의 스코프에 접근을 가능하게 해줍니다. 자바스크립트에서 클로저는 함수가 생성될 때마다 생성됩니다.

라고 하는데... 아 어렵다...

일단, 말이 아닌 코드로 이게 closure 라는 것을 살펴보자!

function outer(){
  const name = 'king';
  console.log(name)
}
outer() //king
console.log(name) //error

당연하다. 변수는 함수 내부에서 선언되어 있기 때문에 함수 바깥에서 name을 읽을 수 없다. 그러면 바깥에서 name을 읽을 수 있는 방법이 있을까?

function outer(){
  const name = 'king';
  console.log(name);
  return function inner(){
    const say = 'hi!'
    console.log(say,name)
  }
}
const doOuter = outer() // king
doOuter() // hi! king

outer 함수가 종료 되었기 때문에, doOuter에서 다시 name을 읽을 수 없을 것이라고 생각했지만, outer내부의 inner함수가 선언될 때 outer의 scope로 inner가 함께 번들로 묶이기 때문에 name을 사용할 수 있게 된다.

번들로 함께 묶인다. = Closure 이다!

즉, 내부에 선언된 함수가 외부 함수의 지역변수를 참조하고 있다. 외부 함수의 지역변수를 내부 함수가 참조하고 있기 때문에, 외부함수가 종료 되었음에도 불구하고 외부함수의 변수는 제거 되지 않고 내부함수가 참조할 수 있는 것이다.

이렇게 복잡하고도 사용도 많이 어려워 보이는 Closure를 왜 쓸까?

1. 전역변수를 줄일 수 있다.
전역변수를 사용하는 것은 최대한 지양하는 것이 좋다. 어디서든 참조할 수 있기 때문에 코드를 작성하는 과정에서 이로인한 오류가 발생할 수 있다.
다만, 변수를 한 번만 쓰는데 전역변수가 아니면 읽을 수 없는 상황일 경우 closure를 통해 이를 해결할 수 있다!

2. 상태유지가 가능하다.

const increase = function () {
	let num = 0;
  	return ++num;
}
console.log(increase()); // 1
console.log(increase()); // 1
console.log(increase()); // 1

위의 코드는 increase를 매번 호출될 때마다 num=0 으로 다시 선언되면서 1이 출력된다!

하지만, 클로저를 이용하여 원하는대로 증가 시킬 수 있는데

const increase = (function () {
	let num = 0;
  	return function() {
    		return ++num
    }
})();
console.log(increase()); // 1
console.log(increase()); // 2
console.log(increase()); // 3

코드가 실행되는 과정은 다음과 같다.

  1. 즉시 실행된 함수 (); 에 의해 반환된 익명함수가 increase에 할당된다.
  2. increase에 할당된 함수는 자신을 기억하는 클로저이다.
  3. 익명함수가 외부함수의 num을 클로저에 의해 참조할 수 있기 때문에 호출 하면 이전의 변수의 값이 기억되고 증가하도록 만들 수 있다.
profile
안녕하세요!

0개의 댓글