JS 클로저, 클로저의 활용 사례

가까이

걸쇠는 기능과 환경의 조합오전.
함수와 환경의 조합입니다. 이 진술에 따르면 어떤 함수든 환경과 결합하기만 하면 되기 때문에 모든 함수를 클로저로 생각할 수 있습니다. 그러나 모든 기능이 결론이 되는 것은 아니지만 이 원리에 따라 기능과 환경이 결합된다. 어떤 특정 목적(데이터 보존, 정보 은닉 등)현상으로 사용될 때 폐쇄라고합니다. (분명히 패스너에 대한 표준 정의는 없습니다. 각각은 다른 문장으로 설명되지만 의미는 비슷합니다.)

function addBy(x) { // 본문 외부함수
  return function(y) { // 본문 내부함수
    return x + y;
  }
}

const addBy3 = addBy(3);
console.log(addBy3(5)); // 8

const addBy10 = addBy(10);
console.log(addBy10(5)); // 15
console.log(addBy3(1)); // 4

클로저는 위의 코드에서 사용됩니다. 내부 기능과 환경.

addBy(3)가 호출되고 반환 값은 변수 addBy3에 있습니다. 내부함수할당된 외부함수완전히 완료되었습니다. 즉, 실행 컨텍스트에서 제거되고 소멸되었습니다. 실행 컨텍스트가 종료되면 추가 메모리 사용을 방지하기 위해 가비지 수집되고 정보가 손실됩니다. 더 외부함수즉, 에서 변수 x를 참조할 수 없습니다.
다음 줄에서 addBy3(5) 호출 내부함수의 y 매개 변수에 5를 전달하는 것은 당연합니다. 외부함수3+5=8의 결과가 반환됩니다. 왜냐하면 3, x는 저장된 것처럼 에서 참조하기 때문입니다.

어떤 현상을 이용하기 때문입니다. 실행 컨텍스트가 소멸되고 가비지 수집되어야 합니다. 지역변수(x)를 참조하는 내부함수가 외부로 전달(addBy3, addBy10)된 경우 그것은 예외가 되고 x는 사라지지 않습니다. 이렇게 클로저로 이미 생명주기가 끝난 외부함수의 변수를 내부함수가 참조하는 것가능하다

이제 걸쇠가 보입니다.

  1. 함수 addBy10과 환경 x=10의 조합.
  2. 함수 addBy3와 환경 x=3의 조합.


클로저 사용 사례

다음은 클로저를 사용한 예입니다. 폐쇄는 실제로 어떤 상황에서 발생합니까?

데이터 보존

function getFoodRecipe (foodName) {
  let ingredient1, ingredient2;
  return `${ingredient1} + ${ingredient2} = ${foodName}!`;
}

console.log(getFoodRecipe("하이볼")); // undefined + undefined = 하이볼!

성분1과 성분2에 어떻게 값을 할당할 수 있나요? 스코프 외부에서 내부에 접근(참조)할 수 없습니다. 작동하지 않는 기능이라 아직은 데이터를 보관할 필요가 없습니다.

function createFoodRecipe (foodName) {
  const getFoodRecipe = function (ingredient1, ingredient2) {
    return `${ingredient1} + ${ingredient2} = ${foodName}!`;
  }
  return getFoodRecipe;
}

const highballRecipe = createFoodRecipe('하이볼');
highballRecipe('콜라', '위스키'); // '콜라 + 위스키 = 하이볼!'
highballRecipe('탄산수', '위스키'); // '탄산수 + 위스키 = 하이볼!'
highballRecipe('토닉워터', '연태고량주'); // '토닉워터 + 연태고량주 = 하이볼!'

클로저를 사용하여 외부에서 매개변수에 액세스하고 다른 값을 할당하고 출력했습니다. 또한, “하이볼”은 데이터가 저장된 것처럼 유지되기 때문에 게인 팩터로 지정하지 않아도 “하이볼”이 계속 출력됩니다. 이런 식으로 데이터를 얻을 수 있습니다. “하이볼”은 한때 트랜스퍼 팩터로 전해져 다양한 제형이 생산되었습니다.

정보 숨기기

function makeCalculator() {
  let displayValue = 0;

  return {
    add: function(num) {
      displayValue = displayValue + num;
    },
    subtract: function(num) {
      displayValue = displayValue - num;
    },
    multiply: function(num) {
      displayValue = displayValue * num;
    },
    divide: function(num) {
      displayValue = displayValue / num;
    },
    reset: function() {
      displayValue = 0;
    },
    display: function() {
      return displayValue
    }
  }
}

const cal = makeCalculator();
cal.display(); // 0
cal.add(1);
cal.display(); // 1
console.log(displayValue) // ReferenceError: displayValue is not defined

마지막 줄과 같이 displayValue를 표시하려고 하면 참조 오류가 발생합니다. 재할당으로 값을 변경하는 것은 물론 불가능합니다. 이처럼 변수를 외부에서 접근(참조)하거나 변경할 수 없도록 숨길 때 사용합니다. 다른 언어의 비공개와 같습니다.


검토

스코프, 클로저, 자바스크립트 개념을 몰라서 예제 코드를 보고 리턴을 따라해보니 실행 결과가 예측 가능하고 ‘어떤 값을 리턴할까’ 하는 생각에 더 이상의 질문은 없었습니다. 그냥 받아 들였습니다만, 개념적으로 보면 어디선가 모순(실행 컨텍스트, 범위…)을 만들어낸 코드였습니다.

클로저의 개념을 이해하는 데 정말 어려움을 겪었습니다. Clojure 덕분에 Metakognition을 만들었습니다. 읽으면서 이해했는데 말로 설명하려니 머리가 복잡해서 말이 안나오네요…

그러나 이제 저는 클로저가 객체가 아니라 현상이라는 것을 압니다. 가비지 콜렉션 예외와 특정 목적을 사용하는 메소드를 구현하고자 할 때 사용할 수 있는 일종의 패턴이라는 것을 알게 되었습니다. 3일 걸렸지만 그만한 가치가 있었습니다!