Javascript

Javascript Closure

muyeon 2024. 4. 29. 21:59

클로져를 알기위해서는 실행 컨텍스트에 대해 알아야 한다. 

https://muyeon95.tistory.com/317

 

실행 컨텍스트

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다. 이는 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이다. 자바스크립트는 어떤 실행 컨텍스트

muyeon95.tistory.com

 

클로져는 무엇이고 어떻게 활용할 수 있을까?

정의

 

MDN : 함수와 함수가 선언된 어휘적 환경의 조합

 

????????????

확실히 MDN 이 만능은 아니다.

 

코어 자바스크립트 : 어떤 함수 A 에서 선언한 변수 a 를 참조하는 내부 함수 B를 외부로 전달할 경우 A 의 실행 컨텍스트가 종료된 이후에도 변수 a 가 사라지지 않는 현상

 


ex code

 

1)

function something() {
	const x = 10;
    function sum(y) {
    	return x + y; // something 함수에서 선언한 x 변수 참조
    }
    return sum; // 내부함수 sum 을 외부로 전달
}

const some = something();
console.log(some(3)); // 13
// x 변수가 사라지지 않는다.

 

 

2)

function sum(x) {
	return function (y) {
    	return x + y;
    }
}

const add = sum(2);
console.log(add(7));

 

 

1. 코드 평가

  •  첫번째로 Global 에 LexicalEnvironment 를 생성하고 전역 코드 평가가 이루어 진다.
  •  코드 평가에서는 sum 함수와 add 변수를 호이스팅해 record 에 add 와 sum 함수를 기록해둔다.
  •  현재 전역 코드 평가가 이루어지고 있기 때문에 outer 에는 null 이 할당된다.
  •  콜 스택에 Global 의 LexicalEnvironment 를 push 하게 된다.
  •  코드 평가 과정 종료

 

2. 코드 순차적으로 진행

  •  add 변수에 값을 할당하기 위해 sum 함수를 호출한다.
  •  Global 의 LexicalEnvironment 코드 평가 과정과 동일하게 sum 함수도 LexicalEnvironment 를 생성
  •  sum 함수 내부의 코드 평가 진행
  •  코드 평가에서는 매개변수 x 와 return 문에 있는 익명함수를 호이스팅해 record 에 기록해둔다.
  •  outer 에는 상위 스코프인 Global 의 LexicalEnvironment 를 가리킨다.
  •  콜 스택에 sum 의 LexicalEnvironment 를 push 하게 된다.

 

  •  sum의 LexicalEnvironment 의 outer 는 함수가 호출되어 평ㅇ가되는 시점이 아닌 함수가 선언되는 시점에 결정된다.
  •  Global 의 LexicalEnvironment 코드 평가 과정에 sum 함수가 선언되었으니 sum 의 LexicalEnvironment outer 에는 Global 의 LexicalEnvironment 를 가리키게 된다.

 

  •  sum 의 코드 평가 과정이 종료되어 코드가 한 줄씩 실행된다.
  •  매개변수 x 에는 인자로 넘겨준 2를 할당
  •  record 안에 x 변수에 2를 기록
  •  이후 실행할 코드가 없으니 sum 의 LexicalEnvironment 는 콜 스택에서 pop 된다.
  •  Global 의 LexicalEnvironment 로 돌아와 add 변수에 sum 함수의 리턴값인 익명함수를 할당한다.
  •  record 에 있는 add 변수에 익명함수를 할당한다.
  •  마지막 전역 코드인 console.log 를 실행하기 위해 add 함수를 호출하게 된다.

 

3. add 함수 호출

  •  add 함수에 호출이 일어나면 add 에 LexicalEnvironment 를 생성
  •  add 함수 내부 코드 평가
  •  매개변수 y 를 호이스팅해 record 에 기록
  •  outer 에는 sum 의 LexicalEnvironment 를 가리키게 한다.

여기서 이상한 점은 현재 콜 스택에는 Global 의 LexicalEnvironment 만 존재한다.

어떻게 add 의 LexicalEnvironment 의 outer 는 sum 의 LexicalEnvironment 를 가리키게 할 수 있을까?

이런 특성 때문에 클러져라는 현상이 일어난다.

 


활용

1) before

let cnt = 0;
function cntPlus() {
	cnt = cnt + 1;
}

console.log(cnt);
cntPlus();
console.log(cnt);

// 1억개의 코드
cnt = 100;
// 1억개의 코드
cntPlus();
console.log(cnt);

전역으로 선언했을 때 위와같은 문제가 발생한다.

이를 해결하기 위해서 cnt 를 은닉화해 접근을 막고 cnt 의 state 를 유지할 수 있다.

 

 

2) after

function closure() {
	let cnt = 0;
    function cntPlus() {
    	cnt = cnt + 1;
    }
    function setCnt(value) {
    	cnt = value;
    }
    function printCnt() {
    	console.log(cnt);
    }
    return {
		cntPlus,
        setCnt,
        printCnt,
	}
}

const cntClosure = closure();
console.log(cntClosure);
cntClosure.printCnt();
cntClosure.cntPlus();
cntClosure.printCnt();
cntClosure.printCnt();
cntClosure.setCnt(100);
cntClosure.printCnt();

 

 

 

 

 


참고 링크

 

https://poiemaweb.com/js-closure

 

Closure | PoiemaWeb

클로저(closure)는 자바스크립트에서 중요한 개념 중 하나로 자바스크립트에 관심을 가지고 있다면 한번쯤은 들어보았을 내용이다. execution context에 대한 사전 지식이 있으면 이해하기 어렵지 않

poiemaweb.com

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

 

Closures - JavaScript | MDN

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closur

developer.mozilla.org

https://ko.javascript.info/closure

 

변수의 유효범위와 클로저

 

ko.javascript.info

https://www.youtube.com/watch?v=LL0DGc5pg7A

https://www.youtube.com/watch?v=PJjPVfQO61o