<JS> 클로저와 클로저의 예제

togongs·2021년 8월 4일
0

2021

목록 보기
10/30

클로저 함수의 정의

자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저(Closure)라고 부른다.
자신이 생성될 때의 환경(Lexical environment)을 기억하는 함수다라고 할 수 있다.

이해해보자면... 외부함수가 이미 반환되었어도 외부함수 내의 변수는 이를 필요로 하는 내부함수가 하나 이상 존재하는 경우 계속 유지한다는 것?

전역변수와 지역변수

전역변수는 언제든지 누구나 접근할 수 있고 변경할 수 있다. 이는 의도치 않게 값이 변경될 수 있다는 것을 의미한다

var counter = 0;

    function increase() {
      return ++counter;
    }

    incleaseBtn.onclick = function () {
      count.innerHTML = increase();

여기서 counter는 전역변수로 사용된다

function increase() {
      // 카운트 상태를 유지하기 위한 지역 변수
      var counter = 0;
      return ++counter;
    }

    incleaseBtn.onclick = function () {
      count.innerHTML = increase();
    };

여기서 counter는 함수increase의 지역변수로 사용된다.
지역변수로 변경하여 의도치 않은 상태 변경은 방지했다. 하지만 변경된 이전 상태를 기억하지 못한다

이전 상태를 기억하도록 클로저를 사용해보자

    var increase = (function () {
      // 카운트 상태를 유지하기 위한 자유 변수
      var counter = 0;
      // 클로저를 반환
      return function () {
        return ++counter;
      };
    }());

변수 increase에는 함수 function () { return ++counter; }가 할당된다. 이 함수는 자신이 생성됐을 때의 렉시컬 환경(Lexical environment)을 기억하는 클로저다

전역변수 대신 지역변수를 사용하는 이유는
상태 변경이나 가변(mutable) 데이터를 피하고 불변성(Immutability)을 지향하는 함수형 프로그래밍에서 부수 효과(Side effect)를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이기 위해 클로저는 적극적으로 사용된다.

특징 1) 함수를 리턴하는 함수 예제

const adder = x => y => x + y;
adder(5)(7) // 12

이거를 어떻게 해석할 수 있나?
adder = x은
adder = (x)과 같고
adder(x)와 같다

따라서, 위의 예제는 아래랑 똑같다.

const adder = fuction (x) {
return function (y) {
return x + y;
}

arrer = x 는 function(x)를 부르고
화살표 함수를 통해 function(y)를 리턴했다. 그리고
function(y)는 화살표 함수를 통해 x+y를 리턴했다.

특징 2) 외부함수와 내부함수

리턴하는 함수에 의해 스코프가 구분된다.
여기서 변수가 선언된 곳이 중요한데...

const adder = fuction (x) {
return function (y) {
return x + y;
}

위의 예제에서는 변수 x와 y가 선언된 곳이 다르죠?
x는 외부함수가 되고 y는 내부함수가 되는데
안쪽 스코프인 y는 바깥 스포크 x로 접근이 가능하지만
x에서 y로는 접근이 불가능하다.

장점 1) 데이터를 보존하는 함수

일반적인 함수는 함수 실행이 끝나면 함수 내부의 변수를 사용할 수 없다.
이와 다르게 클로저는 외부 함수의 실행이 끝나도 외부함수 내 변수가 메모리에 저장된다.

클로저 모듈 패턴이란?

const makeCounter = () => {
    let value = 0;

    return {
        increase: () => {
            value = value + 1
        },
        decrease: () => {
            value = value - 1
        },
        getValue: () => value
    }
}

increase, decrease, getValue 와 같이 내부 함수를 여러개를 포함한 하나의 객체를 만들 수 있다.

여기서 value를 지역변수로 사용했다.

모듈 패턴의 예제

let add = function(x) {
  let sum = function(y) {
    return x + y;
  }
  return sum;
}

let foo = add(1);
foo(3);
let total = foo(6);

total의 값은?

함수 add(function(x))는 x를 매개변수로 하며, 함수 sum(function(y))을 반환한다.
add(1)은 x에 1을 넣으므로 1+y 가 리턴된다.
foo = 1+y
foo(6) = 1+6 따라서 7이 된다.

클로저를 사용하는 방법?

클로저는 내부에 선언된 함수가 외부함수의 지역변수를 사용해 줬을 때만 클로저라고 선언된다.

function outer() {
  let name = 'kyle';
  if (true) {
    let city = 'seoul';
    return function inner() {
      console.log(city);
     console.log(name);
    };
  }
}

위의 예시를 살펴봤을 때,
inner함수에도 클로저를 사용하고 싶으면 name 변수를 사용해주면 된다.

profile
개발기록

0개의 댓글