[Javascript] closure

JungChihoon·2020년 2월 19일
2

Javascript

목록 보기
4/6

한 줄 요약

closure는 외부함수의 자유변수에 접근할 수 있는 내부함수 또는 그 환경을 말한다.

ex 1.
function outer(){
  var name = 'chanho'
  return function(){
    return name;
  }
}

ex 2.
function outer() {
  var count = 0;
  return {
    increment: function(){
      count++
    },
    decrement: function(){
      count--
    },
    getValue: function(){
      return count
  }
}

closure 설명

모질라에 따르면 '클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다.' 라고 나와있다.
간단하게 정리하면 함수 밖에서 선언된 변수를 함수 내부에서 사용할 때 클로저가 생겨난다고 할 수 있다.

function outer(){ 
    var name = 'yuddomack';
    function inner(){ 
      console.log(name);
    }
    return inner;
}


var innerFunc = outer();
innerFunc();

<외부 변수(name)를 함수 내부(inner)에서 사용>

위 코드에서 outer함수는 메모리 상에 아래와 같은 모습을 하게된다. 

<메모리에서 outer 함수의 모습>


이제 var innerFunc = outer()를 통해서 inner 함수를 반환받게 되는데, 일반적으로 함수가 종료되면 메모리에서 소멸하기 때문에 아래와 같은 모습을 하게 된다..

<outer 함수가 종료되며 name에 대한 참조를 잃은 모습>


때문에 일반적으로, innerFunc를 호출해도 name에 대한 참조는 메모리에서 소멸하여 호출이 불가하게 된다.

하지만 클로저는 이러한(외부 변수와 같은) 환경 자체를 통째로 기억하는 공간을 형성한다.

<outer 영역은 소멸되었지만 클로저가 생성되어 여전히 참조 가능>

이러한 이유로 innrFunc는 여전히 자신의 외부에서 생성된 name 이라는 변수를 참조할 수 있게 된다.


  • 설명 참고
  1. scope : 코드작성 시 생김.(lexical scope)

  2. let,  const  : 메모리공간은 생김, 이를 호이스팅이라고 하나 var과 같은 호이스팅의 효과는 아님.

  3. execution context 
    어떤 함수가 호출되면, scope에 따라서 scope마다 메모리테이블이 생기고 이를 실행컨텍스트(execution context)라고 부른다.
    실행컨텍스트는 실행시점이 중요함

4.  자유변수:  클로저에 의해 참조되는 외부함수의 변수

  1. closure
    클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프: 선언되었을 때 환경)에 접근할 수 있는 함수 또는 클로저는 자신이 생성될 때의 환경(Lexical environment)을 기억하는 함수

closure 활용방법 및 예제

복습 1. testbuilder

실패사례

결과값 -> undefined

해결 방법

첫번째 : var을 let으로 바꿈 (182, 183번째 줄)

두번째 해당 부분을 IIFE(즉시실행함수)사용 (164, 191번째 줄)

복습 2.

function a(){
  var b = 100;
  function c(){
    return b + 100;
  }
  c()
}

var d = a()

console.log(d)의 값은?
.
.
.
.
.
.
.
답: undefined
왜 undefined일까?
.
.
.
.
.
.
.
.
.

a함수는 c함수를 실행하였지만 반환하지 않음.
따라서 c()  -> return c();로 변경

closure 활용방법

1. 상태유지

클로저가 가장 유용하게 사용되는 상황은 현재 상태를 기억하고 변경된 최신 상태를 유지하는 것

ex 1.  
참조 : https://poiemaweb.com/js-closure

2. 캡슐화

클로저 영역이 별도로 생성되는 모습은 마치 객체를 생성한 모습과 유사하다.
자바스크립트의 var는 전역적인 특성을 지니고 있지만 클로저의 특성을 이용하면 private 변수를 갖는 클래스 형태로 만들 수 있다.

student 함수의 반환값을 보면, 외부 변수(name, score 파라미터)가 함수의 내부(익명함수)에서 사용되는 모습을 보이기 때문에 클로저의 생성을 짐작할 수 있다.

프로토타입을 사용한 객체 생성도 가능하지만 이렇게 클로저를 이용하는 것으로도 클래스 객체의 모습을 흉내낼 수 있다.

<동일한 student 함수이지만 각각의 클로저가 독립적으로 생성되는 모습>

3. 전역변수 사용의 억제

전역변수를 사용하게 되면 의도치 않게 변수의 수정이 발생할 수도 있으므로 이를 방지하기 위해 closuer사용
참조: https://poiemaweb.com/js-closure

4. 은닉화

자주 나오는 예제

privateCounter 접근시도  ->  역시 실패

그래서 변수에 counter를 할당한 후 변수를 본 결과   ->  오른쪽에 결과로 나오는 것들이 public //  counter에는 있지만 안나오는 것들이 private

위의 결과로 깨닫게 된 것 

  • public한 부분과 private한 부분에 대한 이해

그리고

  • 자유변수 privateCounter 를 수정을 할 수있는 방법은 외부에서 호출되더라도 선언되었을 때의 환경을 기억하는 특성이 있는 클로저 함수를 이용하면 된다.

참조

https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures

https://poiemaweb.com/js-closure

https://meetup.toast.com/posts/90

https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%81%B4%EB%A1%9C%EC%A0%80Closure

https://medium.com/@khwsc1/%EB%B2%88%EC%97%AD-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80-javascript-scope-and-closures-8d402c976d19

profile
주니어 개발자

0개의 댓글