[JS] 클로저

박시은·2023년 6월 24일
0

JavaScript

목록 보기
26/58
post-thumbnail

▶ scope

scope에 대해서 자세히 알고싶다면? 클릭

아래 코드는 어떻게 동작 한 것일까? 스코프에 주목해보자

let value0 = "value0";

function fn1() {
  let value1 = "value1";
  console.log(value0, value1);
}
fn1();
value0value1
ScopeGlobal Scopefn1 함수의 Local Scope
  • Global Scope(전역): 전체 스크립트에 접근 가능
  • Local Scope(지역): 해당 함수 내에서만 접근 가능

그렇다면 value0의 값은 js는 어떻게 가져올까?

js는 가장 먼저 Local을 찾는데, Local에 value0이 없으므로 Script에서 value0을 가져온다.




▶ lexical scoping

아래 코드는 왜 동작을 하지 않는 것일까? 역시 스코프에 주목해보자

let value0 = "value0";
function fn2() {
  let value2 = "value2";
  console.log(value0, value1, value2);
}

function fn1() {
  let value1 = "value1";
  console.log(value0, value1);
  fn2();
}
fn1();
value0value1value2
ScopeGlobal ScopexLocal Scope
  • 위 코드가 에러가 발생하는 이유는 fn1() 함수 내에서 선언된 value1 변수는 fn1()의 지역 스코프에 속한다. 따라서 fn2() 함수에서 value1 변수에 접근하려고 하면 에러가 발생한다.

  • 마찬가지로 fn2() 함수에서 선언된 value2 변수는 fn2() 지역 스코프에 속하므로, fn1() 함수에서 접근할 수 없다.

  • 이처럼 함수의 유효범위는 함수가 어디서 실행됐느냐가 아닌, 어디서 정의됐느냐에 따라 달라지는데, 이를 lexical scoping(렉시컬 스코핑) 또는 static scope라고 부른다.




▶ 클로저

  • MDN에서는 클로저(Closure)는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이라고 정의하였다.

  • 즉, 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수를 말한다.

  • 이를 간단히 말하자면 클로저는 중첩된 함수가 외부 스코프에서 선언된 변수에 접근할 수 있는 기능을 말한다.

아래 코드 참조: 클로저Closure란

// Counter 예제
const btn = document.querySelector('button')
btn.addEventListener('click',handleClick)

let count = 0
function handleCilck(){
  count++
  return count
}

//위와 같은 경우에 count를 전역변수로 사용해줘야 count가 증가를 해줄 수 있음
//이럴경우 클로져를 사용해서 해결할 수 있다.


// Counter Closure 예제
const btn = document.querySelector('button')
btn.addEventListener('click',handleClick())

function handleCilck(){
  let count = 0
  return function (){
    count++
    return count
  }
}
// 위와 같이 작성해 준다면 외부함수(handleClick)의 lexical environment를 참조하는 함수를 
// btn의 콜백함수로 이용해 전역객체 없이 구현할 수 있다.

▷ Closure를 사용하는 이유

  • 클로저는 자신이 생성될 때의 환경(Lexical environment)을 기억해야 하므로 메모리 차원에서 손해를 볼 수 있지만, 현재 상태를 기억하고 변경된 최신 상태를 유지하려고 할 떄 유용하게 사용된다.
  • 클로저를 사용하면 변수의 소멸을 막고, 필요할 때마다 값을 다시 사용할 수 있다. 예를 들어, 카운터 함수를 만들고자 할 때 클로저를 사용해서 내부 카운트를 기억하게끔 할 수 있다.
// (코드참조)
function Counter() {
  // 카운트를 유지하기 위한 자유 변수
  var counter = 0;

  // 클로저
  this.increase = function () {
    return ++counter;
  };

  // 클로저
  this.decrease = function () {
    return --counter;
  };
}

const counter = new Counter();

console.log(counter.increase()); // 1
console.log(counter.decrease()); // 0
  • 비슷한 형태의 코드의 재사용율을 높일 수 있다.
// 새로운 태그를 만들 수 있는 함수 Closure 구현
const order = (food) => {
  console.log(food + "을(를) 주문하셨습니다.");
  return function (drink) {
    return drink + "을(를) 추가로 주문하셨습니다."
  }
} 

const orderBurger = order("햄버거");
const orderPizza = order("피자");
console.log(orderBurger("콜라"));
console.log(orderPizza("사이다"));



📎참조

profile
블로그 이전했습니다!

0개의 댓글