FE/JavaScript

[JS] 클로저 (Closure)

mandelina 2022. 5. 11. 12:15

들어가기에 앞서,

MDN에서 클로저의 정의를 보자 .

 

" 클로저 함수는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다. "

 

클로저를 알기 전 '렉시컬 스코프' 에 대해 알아보자.

 

 

🚀 렉시컬 스코프 (정적 스코프)

 

- 자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정한다.

 

- 함수가 호출된 위치는 상위 스코프 결정에 어떤 영향도 주지 않는다.

 

- 함수의 상위 스코프는 언제나 자신이 정의된 스코프다. 

  ( 함수가 호출될 때마다 함수의 상위 스코프를 참조할 필요가 있기 때문) 

 

 

🚀 클로저

 

- 폐쇄된 공간 안에 데이터에 접근하기 위한 테크닉

- 내부함수의 외부 함수 접근(권한) 테크닉

- 변수 은닉 메모리 효율, 코드효율을 극대화 하기위해 사용

 

const x =1 ;

function outerFunc(){
    const x =100
    innerFunc();
}

function innerFunc (){
    console.log(x);
}

outerFunc();

 

innerFunc을 outer밖에 정의하였고 , outerFunc안에서 호출한 상태이다 .

이경우 innerFunc이 호출된 outerFunc스코프 상의 x값 100을 출력할것이다라고 예상할수도 있지지만

innerFunC은 x=100에 접근하지 못한다. 정의된 곳을 기준으로 상위 스코프에 접근하여  x=1의 값을 출력한다.  

 

[결과]

 

 

🚀 [예제1]

function makeAdder(x) {
    var y = 1;
    return function(z) {
        y = 100;
        return x + y + z;
    };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  
console.log(add10(2));

 

함수 실행시 클로저 값에 저장된 x, y 값에 접근하여 값을 계산한다.

여기서 클로저는 add5 , add10이 된다. 

add5add10 functuon이고 , 그 안에 변수값을 보면 

add5에는 x=5 , y=100가 있을것이고 , add10에는 x=10,y=100으로 있을것이다.

 

add함수 자체에 x값이 정의되어있지 않지만 add함수가 정의된 곳을 기준으로 렉시컬 스코프를 접근 할 수 있기 때문에 x값에 접근 할 수 있었던 것이다.  

 

🚀 [예제2]

// 1
const x = 100;

function a() {
  const x = 1;
  b();
}

function b() {
  console.log(x);
}

a(); // 100
b(); // 100

 

a()와 b()는 같은 스코프 상에서 정의되어있고, b()를 a() 안의 중첩함수로 호출하였다.

하지만 a()안에서 호출되었다고 해서 x=1을 접근할수 없다.

그렇다면 렉시컬 스코프 기준 상위 스코프는 x=100으로 정의되어 있으므로 a() b() 모두 100이 호출된다.

 

// 2

const xx = 100;

function a() {
  const xx = 1;
  function b() {
      console.log(xx);
  }
  b();
}

a();

 

 

a()안에 b()가 정의되었고, 호출되었다. 이 경우 렉시컬 스코프 기준 상위스코프는 a()가 되므로 

xx=1에 접근 가능하다. a()가 호출되고 b()가 호출되었을때  xx값은 1이 된다.

 

(참고로 b()는 a()안에 선언되었으므로 a()와 같은 스코프 상에서 b()를 호출 할 수 없다. )

 

 

🚀 [예제3]

function 승수제조기(){
    let value = 0;
    function 승수(){
        return ++value**2
    }
    return 승수
}

let 승 = 승수제조기();
승()
승()
승()
value //출력할 수 없습니다. 은닉화가 되었기 때문입니다.

 함수를 호출할때 value값이 1씩 증가되면서 value값이 저장되어 호출된다.

 

[결과]

 

 

 

 

끝으로 

- 이런 클로저를 이용하여 private method를 흉내낼 수 도 있다. 이것을 모듈패턴이라 한다.

 

- 클로저가 필요하지 않는 데 다른 함수 내에서 불필요하게 작성하는것은 처리속도와 메모리 소비 측면에서 부정적인 영향을 미친다. 

 

 

생활코딩님 클로저 정의
"부모 함수 안에서 자식 함수를 선언하면 자식함수를 어디에서 호출하더라도 자식함수 안에서 부모함수의 변수에 접근할 수 있습니다. "

 

'FE > JavaScript' 카테고리의 다른 글

[JS] DOM - Event Flow  (0) 2022.05.12
[JS] this  (0) 2022.05.11
[JS] 구조분해 할당  (0) 2022.05.11
[JS] for of 과 for in  (0) 2022.05.11
[JS] 배열의 메소드 - find , filter ,map  (0) 2022.05.11