[JavaScript] JS_개념 및 동작원리 10. Closure

jungeundelilahLEE·2020년 9월 15일
0

# INDEX

1. Values & Data type
2. Operators
3. Control flow
4. Scope & Hoisting
5. Object & Array
6. This
7. Prototype & Inheritance
8. Function
9. Callback function
10. Closure
   10-1. concept
   10-2. example

11. Class
12. Others

10. Closure

10-1. 개념

: 함수와 함수를 둘러싼(=함수가 선언된) 어휘적 환경의 조합

** 어휘적 환경이라함은 외부 함수 안에 정의된 지역변수들이될테고, 외부함수에 전달되는 파라미터를 포함함.

** 그렇다면, 외부함수에 파라미터도 전달되지 않고, 명시적인 지역변수의 선언도 없다면, 이때 내부함수는 클로저인가 아닌가?
: 정의상으로는 클로저인데, 그냥 큰 의미없는.. 클로저의 이점이 없는.. just 내부함수

클로저의 효용 (쓰임 목적)

1) Namespacing (privacy) -> 변수의이름이 적용되는 공간
2) Function factory
3) Partially applied function

  • 자바스크립트에서 변수는 누군가가 기억해주면 살아남음 (그렇지 않으면 사라짐)
  • 함수 안에서 클로저가 형성되면, 그 안에서 선언해준 변수는 함수 안에서만 프라이빗하게 쓰일 수 있음 (변수의 프라이버시를 지켜줄 수 있음) 따라서 데이터를 보호해줄 수 있음 (다른 객체에 접근하기가 쉬운데 이 클로저 내부에서는 접근하기가 어려워짐. 따라서 클로저를 써서 객체를 만들면 지켜낼 수 있음)

  • 함수가 선언될(혹은 생성될) 당시 주변 환경(Lexical Environment)과 함께 갇히는 것을 의미 / 단어의 의미와 마찬가지로 "폐쇄"의 의미
    **Lexical : relating to words

  • 외부 함수의 변수에 접근할 수 있는 내부 함수 (또는 이러한 작동 원리를 일컫는 용어)

  • 주변 환경과 관련하여 생성되는 개념으로, 실행 장소나 시점은 전혀 관계가 없음

  • 아래의 예시에서 innerFn function이 "클로저 함수"라고 할 수 있음

  • 클로저 함수 안에서는

    • 외부 함수의 변수 (outer var)
    • 지역변수 (inner var)
    • 전역변수 (global var)
      의 접근이 모두 가능
function say () {
  const a = 1;
  const b = 2;
  function log () {
    console.log(a + b);
  }
  return log;
}
const func = say(); 	// func변수가 가르키는 값은 function log 
func();		// func function이 실행 
		// => 여기는 say function scope의 외부 
  		//=> but, a값과 b값을 출력할 수 있음 
		//=> 이 이유가 바로 클로저
  • 모든 JS 함수는 선언될 당시 클로저가 형성되며 선언되는 주변환경을 기억함
  • 위의 예제에서 const func = say(); 이 부분에서 say function 이 실행됨으로써, 변수 a 선언, 변수 b 선언, log function 생성됨 / log function은 "선언될 당시 주변 환경과 함께 갇히게 되어", 실제 실행되는 부분이 외부 스코프 또는 한참 이후라도, 함수가 선언될 당시의 lexical environment에 대한 접근이 가능해짐

// 연습 ex) 

function outerFn() {
  let outerVar = "outer";
  console.log(outerVar); //"outer"
  
  function innerFn() {
    let innerVar = "inner";
    console.log(innerVar);
  }
  return innerFn;
}
innerFn();
console.log("-------------")


// 다음의 경우 콘솔에 어떻게 찍힐까?

// 문0) outerFn();
  // "outer"
  // function foo () {return "hello";}

// 문1) outerFn()(); 
  // 함수를 실행한것을 다시 또 실행? 에러? 
  // 오답
  // "outer"
  // "inner"

// 문2) let innerFn = outerFn();
  // 단지 innerFn이라는 새로운 변수를 전역으로 선언한것과 같으므로, 아까의 결과와 같이 "outer"
  // 정답

// 문3) innerFn();
  // 에러 (outerFn안에 innerFn이 있으므로, outerFn이 먼저 실행되어야 하지 않아?)
  // 오답? error?
  // 정답은 "inner"
  
//-----------------아래의 경우, 함수 그대로를 리턴

function foo () {
  return "hello";
}
console.log(foo);

10-2. 유용한 클로저 함수 예

  • 커링 : 함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법
  • 외부 함수의 변수가 저장되어, 템플릿 함수와 같이 사용할 수 있음
  • 클로저 모듈 패턴 : 변수를 스코프 안쪽에 가두어 함수 밖으로 노출시키지 않는 방법
function add(x) {
  return function (y) {
    return x + y;
  }
}
add(1)(5);	//6
// 1은 x로, 5는 y로

let minus = minus(50);
minus(1) //maybe 49
minus(10) //maybe 40
// x의 값(인자)을 고정해 놓고 재사용할 수 있다는 장점이 있음!
// 
profile
delilah's journey

0개의 댓글