[JavaScript] 클로저(Closure) feat. useState

예리에르·2021년 5월 31일
0

JavaScript

목록 보기
5/7

클로저란?

  • 내부함수가 외부함수의 맥락(context)에 접근할 수 있는것을 가르킨다.
function outerFunc() {
  var x = 10;
  var innerFunc = function () { console.log(x); };
  innerFunc();
}

outerFunc();
  • 내부함수는 외부함수의 지역변수에 접근할 수 있다.
function outerFunc() {
  var title = 'coding funny';
  return function() {
    alert(title);
  }
}
innerFunc = outerFunc();
innerFunc
  
  • 내부함수는 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근할 수 있다.
  • innerFuncouterFunc를 호출하고 있다. outerFunc는 실행이 끝났기 때문에 지역변수는 소멸되는 것이 자연스럽다. 하지만 실제 실행결과를 보면 'coding funny'가 출력되는 것을 볼수 있다. 즉, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 의미한다.

✅복잡한 예제

function factory_movie(title){
    return {
        get_title : function (){
            return title;
        },
        set_title : function(_title){
            title = _title
        }
    }
}
ghost = factory_movie('Ghost in the shell');
matrix = factory_movie('Matrix');
 
alert(ghost.get_title()); //'Ghost in the shell'
alert(matrix.get_title()); //'Matrix'
 
ghost.set_title('공각기동대');
 
alert(ghost.get_title()); //'공각기동대'
alert(matrix.get_title()); //'Matrix'

코드를 통해 알 수있는 것들

  1. factory_movie는 객체를 return한다. 이 객체는 메소드 get_title, set_title을 가지고 있다. 메소드는 지역변수 title을 사용하고 있다.
  2. ghost.set_title('공각기동대');는 title의 값을 '공각기동대'로 변경했다. ghost.get_title()에서 '공각기동대'가 나오는 것은 title을 공유하고 있기 때문이다.
  3. ghost와 matrix의 get_title의 결과값이 다르다. 이유는 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문이다.
  4. factory_movie의 지역변수 title은 2행에서 정의된 객체의 메소드에서만 접근 할 수 있는 값이다. 이 말은 title의 값을 읽고 수정 할 수 있는 것은 factory_movie 메소드를 통해서 만들어진 객체 뿐이라는 의미다. JavaScript는 기본적으로 Private한 속성을 지원하지 않는데, 클로저의 이러한 특성을 이용해서 Private한 속성을 사용할 수 있게된다.

클로저를 공부하다보니 React의 useState와 비슷하다는 생각을 하게 되었다.

feat) React Hook useState

  • render() 메소드를 통해 필요한 부분만 업데이트 할 수 있는 클래스형 컴포넌트와 달리함수형 컴포넌트렌더가 필요할 때마다 함수를 다시 호출한다.
  • 함수형 컴포넌트는 props를 인자로 받아 jsx문법에 맞는 리액트 컴포넌트를 리턴하는 것이 함수형 컴포넌트이다. 함수형 컴포넌트에서 상태관리를 하기 위해서는 함수가 다시 호출되었을 때 이전의 상태를 기억하고 있어야 하는데 React Hook은 클로저를 통해서 해결하려 한다.
  • useState메소드는 클로저를 이용해서 함수이 상태를 기억한다.
const customUseState = (initialVal) => {
  let innerState = initialVal;
  const state = () => innerState;
  const setState = (newVal) => {
    innerState = newVal;
  };
  return [state,setState];
}

const [Counter,setCounter] = customUseState(0);
console.log(Counter);
setCounter(1);
console.log(Counter)
  • 위 코드는 클로저 개념을 이용해서 구현한 useState함수이다. 실제로 state와 setState를 사용하는 시점은 customUseState의 호출이 끝난 후이지만, 클로저가 innerState값을 기억하고 있기 때문에 이 후에도 접근할 수 있다.
  • state는 변수 값이기 때문에 customUseState이 호출이 끝나고 나면 그대로 return되어 더이상 변경할 수 없다. 값이 update되어도 참조할 수 없게 된다. 문제를 해결하기 위해 규칙을 만든 후 state값을 useState메소드 위부에 배열 형식으로 저장하는 방법을 선택

😘 useState원리에 대한 내용은 다음에 useState만의 포스트를 게시하겠습니다.

참고)
https://opentutorials.org/course/743/6544
https://yeoulcoding.tistory.com/149

profile
비전공 프론트엔드 개발자의 개발일기😈 ✍️

0개의 댓글