[로운스쿨] 클로저

이로운·2023년 1월 25일
0

동기들에게 클로저를 쉽게 설명하기 위해서 설명했던 자료이다
어려운 단어들은 최대한 배제하고 설명하였다.

클로저를 설명하려면 여러가지 배경 지식들이 있어야한다

  • 실행컨텍스트
  • 아우터와 레코드
  • 호이스팅
  • 스코프
  • 변수

이런 내용들을 모두 설명하려면 초보자들(나도 포함)은 이해를 못하기 쉽상이다

들어가기 전에 호이스팅과 변수 정도는 공부를 해야한다

그럼 시작해보자

렉시컬(언어적) 환경

우리가 코드가 호이스팅 되서 변수가 변화하는 과정을 명시적으로, 즉 눈에 보이게 할 수는 없다
이는 컴퓨터 내부에서 나타나는 변화이기 때문이다
우리가 언어적으로만 표현할 수 있는 환경 그래서 렉시컬(언어적) 환경이라고 칭한다

사용 이유

  1. 변수를 보호하기 위해서
  2. 참조

실행 컨텍스트

컴퓨터는 자바스크립트 코드가 실행되면 전체 코드를 스캔한다(유식한 말로는 파싱한다)
스캔 후 함수와 변수를 스캔 해서 실행 컨텍스트에 호이스팅 한다
나는 실행 컨텍스트를 변수와 함수가 입주하는 아파트 라고 칭한다


첫번째 예제(참조)

이제부터 실행컨텍스트와 코드 칸을 나눠서 작성 해보겠다

실행 컨텍스트(아파트)

3층 301호(3층 렉시컬 환경) y=3(매개변수)

2층 201호(2층 렉시컬 환경) x=3(매개변수)(2에서 삭제)

1층 101호(1층 렉시컬 환경) add : 변수 -> 2에서 함수가 담긴다, makeAdder : f


코드

function makeAdder(x){ // 1
  return function(y){  // 2
    return x + y; // 3
  }
}

const add3 = makeAdder(3); // 4
console.log(add3(2)); // 5
  1. 변수와 함수가 호이스팅 되어서 1층에 자리한다
  2. 위에서 부터 차례대로 코드가 실행된다
  3. 1번 코드 자리가 실행 : 함수이기 때문에 호출부를 찾는다(매개변수를 찾으러)
  4. 호출부에서 매개변수를 찾아온다
  5. 매개변수도 변수이기 때문에 실행 컨텍스트 2층으로 올라간다
  6. makeAdder라는 매개변수가 return 을 만나며 할일을 다하고 실행 컨텍스트 아파트에서 빠진다
  7. makeAdder라는 함수는 2에서 익명함수를 리턴하고 그 함수는 add3이라는 변수에 담긴다
  8. add3이라는 함수는 매개변수를 찾기 위해서 호출부를 확인하고 매개변수는 호이스팅된다(3번 순서와 같다)
    • 이때 2층으로 들어가는게 맞지만 이해를 위해서 3층에 적었다
  9. 3에서 익명함수는 x+y를 리턴한다
  10. y는 내부함수에서 참조가 가능하지만 x는 실행 컨텍스트에서 pop 되었기 때문에 찾을 수 없다 하지만 값은 정확히 나온다

=> 이때 실행컨텍스트에 없지만 값을 참조하는 내부함수를 클로저라고 한다
=> 같은 말이지만 내부함수의 렉시컬 환경이 외부보다 오래 살아있으면 클로저라고 한다

두번째 예제 변수 보호

  let num = 0;

  function addNum(){
    return num++;
  };

let counter = makeCounter();

console.log(counter()); // 0
console.log(counter()); // 1
console.log(counter()); // 2

원리는 위와 같기 때문에 장황하게 설명하지 않겠다
만약 이런 코드를 짰다고 생각해보자
나는 콘솔을 찍을 때 마다 0, 1, 2가 차례로 나오게 하고 싶은것이다

  let num = 0;

  function addNum(){
    return num++;
  };
// 1억개의 코드

num = 100;


// 1억개의 코드

let counter = makeCounter();

console.log(counter()); // 0 -> 100
console.log(counter()); // 1 -> 101
console.log(counter()); // 2 -> 102

사이에 수많은 코드가 있는데 누가 중간에 재할당을 했다고 가정해보자

100부터 시작하게 되어버린다

만약 이것이 이해가 안된다면 호이스팅을 더 공부해야한다

만약 결과는 무조건 0부터 시작해서 1씩 증가해야한다면 나는 let num 이라는 변수를 보호할 필요가 있다
var까지 참조를 막아줄 수 있는 스코프는 함수 스코프이다

이해가 안간다면 변수와 스코프를 공부 해야한다

function makeCounter() {
  let num = 0;

return function(){
return num++;
};
}

let counter = makeCounter();

console.log(counter()); // 0
console.log(counter()); // 1
console.log(counter()); // 2

이렇게 함수로 싸서 보호를 해준다면 완벽히 참조가 불가능 할것이다.
남들도 봤을때 클로저구나 이건 값이 바뀌면 안된다고 생각할 수 있다.
또한 지역변수로 변수를 선언했기 때문에 이 변수는 안전하다
여러 이점이 있기 때문에 꼭 알아둬야한다

추가로 회사마다 다르긴 하지만 IIFE패턴을 쓰는 회사는 클로저로 함수 보호를 하기때문에 알아둬야한다
하지만 요즘은 모듈화를 더 추구하는 분위기이다







profile
이름 값 하는 개발자가 꿈인 사람

0개의 댓글