본문 바로가기
javascript

closure

by rami_ 2024. 3. 27.

colsure는 함수와 그 함수가 선언될 때의 렉시컬 환경(지역 변수, 상위 스코프의 변수, 전역 변수)의 조합이다.

이를 통해 내부 함수는 선언될 당시의 변수와 함수에 접근할 수 있게 되며 이러한 특성은 함수형 프로그래밍 패턴에 매우 유용하게 사용된다.

함수형 프로그래밍 패러다임은 순수 함수와 불변성, 데이터 변환의 중요성을 강조하며 클로저는 이러한 패러다임을 구현하는데 있어서 핵심적인 도구 중 하나이다.

 

데이터 캡슐화, 커링, 상태보존 이벤트 핸들러 등이 있다.

 

클로저의 동작 원리는 1. 함수내부에서 다른 함수를 선언하고 2. 내부 함수가 외부 함수의 스코프에 있는 변수를 참고하고자 할 때, 3. 외부함수가 실행을 마치고 반환된 후에도 내부 함수는 외부 함수의 변수에 대한 참조를 유지함. 4. 이러한 참조는 내부 함수가 실행될때까지 유지되며, 이를 통해 내부 함수는 외부 함수의 변수를 기억한다.

 

이제 예제를 통해 알아보자.

 

1. for문 + setTimeout

for (var i = 1; i <= 3; i++) {
    setTimeout(function() {
        console.log(`i: ${i}`);
    }, i * 1000);
}

 

for문이 실행되면 setTimeout이 실행되게 되는데 이때 for문은 callstack에서 실행되고 setTimeout은 macrotask queue에 등록된다.

총 3개의 setTimeout이 등록되며 delay는 각 1 * 1000, 2 * 1000, 3 * 1000이 된다. for문이 모두 실행된다 eventloop가 callstack이 비고 microtask queue에 등록된 이벤트가 없는것을 확인하면 macrotask queue에 있는 이벤트들을 실행한다. setTimeout들이 실행되며 콘솔로그를 찍게 되는데 이때 i는 4로 종료가 되었으므로 콘솔로그에 i: 4가 1초 뒤, 2초 뒤, 3초 뒤에 찍히게 된다.

 

 

2. closure를 활용한 데이터 캡슐화

function createLogger(message) {
    // 여기에 코드 작성
}

const helloLogger = createLogger('Hello');
const worldLogger = createLogger('World');

helloLogger(); // "Hello" 출력
worldLogger(); // "World" 출력

문제의 조건을 보면 helloLogger를 실행시켰을 때 createLogger의 인자로 넘긴 "Hello"가 출력되며 worldLogger를 실행시켰을 때 createLogger시 인자로 넘긴 "World"가 출력된다.

createLogger의 return 값이 함수이며 먼저 넘겼던 인자값을 closure를 통해 기억해야 함으로

function createLogger(message) {
   return () => console.log(message);
}

 

이렇게 작성해야 한다.

 

 

3. closure를 활용한 데이터 캡슐화

function createCounter() {
    // 여기에 코드 작성
}

const counter1 = createCounter();
const counter2 = createCounter();

console.log(counter1()); // 1
console.log(counter1()); // 2
console.log(counter2()); // 1
console.log(counter2()); // 2
console.log(counter1()); // 3

createCounter를 실행한걸 counter1,2에 담아서 실행시키는데 그렇다면 createCounter의 return값은 함수여야 하며 함수를 호출할 때마다 수가 증가하고있다는 것은 함수 안에 어떤 변수에 값이 담겨 있으며 그 값을 클로저를 통해 기억하고있다는 것이다. 함수가 실행되는 횟수만큼 count가 증가한다.

function createCounter() {
   let count = 0;
   
   return () => ++count;
}

 

** count++로 반환하면 증가 전의 값을 반환함. ++count로 하면 증가시킨 후 반환할 수 있음.

 

 

'javascript' 카테고리의 다른 글

[LEARN-JS] Array  (0) 2024.08.06
[LEARN-JS] String, Jest  (0) 2024.07.23
scope  (1) 2024.03.26
hoisting  (0) 2024.03.26
자바스크립트의 비동기처리  (0) 2024.03.18